/* === Admin design tokens === */
:root {
    --bg:           #f8f4ec;
    --surface:      #ffffff;
    --surface-alt:  #fbf8f1;
    --primary:      #2D5040;
    --primary-dark: #1B3A2A;
    --accent:       #C9A227;
    --accent-soft:  #f5e9b6;
    --text:         #1A1F18;
    --muted:        #5C5C5C;
    --border:       #E8DFC9;
    --border-soft:  #f0e9d6;
    --danger:       #b91c1c;
    --danger-soft:  #fee2e2;
    --success:      #047857;
    --success-soft: #d1fae5;
    --radius-sm:    6px;
    --radius:       10px;
    --radius-lg:    16px;
    --radius-pill:  999px;
    --shadow-sm:    0 1px 2px rgba(26, 31, 24, .06), 0 1px 3px rgba(26, 31, 24, .04);
    --shadow:       0 4px 16px rgba(26, 31, 24, .08), 0 1px 4px rgba(26, 31, 24, .05);
    --shadow-lg:    0 12px 40px rgba(26, 31, 24, .12);
    --transition:   .2s ease;
}

/* === Self-hosted fonts (same files as public) === */
@font-face { font-family: 'Cinzel'; font-style: normal; font-weight: 400 700; font-display: swap; src: url('/assets/fonts/catalog/cinzel/cinzel-400-latin.woff2') format('woff2'); unicode-range: U+0000-00FF; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('/assets/fonts/catalog/inter/inter-400-latin.woff2') format('woff2'); unicode-range: U+0000-00FF; }

/* === Cross-document view transitions (2026) ===
 * Chrome 126+, Edge, Safari TP fade smoothly between admin pages — no
 * SPA framework needed. Browsers without support fall back to instant
 * navigation (no breakage). The header is excluded from the cross-fade
 * via `view-transition-name: admin-header` so it stays visually stable
 * while only the <main> content animates — eliminates the flicker the
 * user reported on title + nav. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: .22s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
.admin-header { view-transition-name: admin-header; }
.admin-main   { view-transition-name: admin-main; }
::view-transition-old(admin-header),
::view-transition-new(admin-header) { animation: none; }

/* === Reset === */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body.admin,
body.ambassador {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.6;
    font-size: 15px;
    min-height: 100vh;
}
*:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.btn:focus-visible { outline-offset: 4px; }
img { max-width: 100%; height: auto; display: block; }

/* === Typography === */
h1, h2, h3, h4 { font-family: 'Cinzel', Georgia, serif; color: var(--primary-dark); line-height: 1.2; font-weight: 600; }
h1 { font-size: 2rem; margin-bottom: 1.5rem; letter-spacing: -.005em; }
h1::after { content: ''; display: block; width: 50px; height: 3px; background: var(--accent); margin-top: .65rem; }
h2 { font-size: 1.4rem; margin-bottom: 1rem; }
h3 { font-size: 1.1rem; margin-bottom: .5rem; }
.admin code,
.ambassador code { font-family: 'SF Mono', Menlo, Consolas, monospace; font-size: .85em; background: var(--surface-alt); padding: 1px 6px; border-radius: 4px; color: var(--primary-dark); }
.admin-main a:not(.btn) { color: var(--primary); text-decoration: none; transition: color var(--transition); }
.admin-main a:not(.btn):hover { color: var(--accent); }
.ambassador-main a:not(.btn) { color: var(--primary); text-decoration: none; transition: color var(--transition); }
.ambassador-main a:not(.btn):hover { color: var(--accent); }

/* === Sortable + filterable + paginated list tables (admin-tables.js) === */

/* Horizontal-scroll container that admin-tables.js wraps around every
 * .admin-table. overflow-x:auto only shows a scrollbar when the table is
 * actually wider than the viewport (i.e. on mobile), so desktop is unaffected
 * while wide tables scroll sideways instead of overflowing or being clipped. */
.admin-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Filter row: lives inside <thead>, immediately UNDER the column-header
 * row, spanning all columns. Full-width input, counter on the right. */
.admin-table-bar-row td.admin-table-bar-cell {
    padding: .55rem .9rem !important;
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border);
}
.admin-table-bar {
    display: flex; align-items: center; gap: .75rem;
}
.admin-table-search {
    position: relative;
    flex: 1; min-width: 0;
    display: flex; align-items: center;
}
.admin-table-search svg {
    position: absolute; left: .85rem; top: 50%;
    transform: translateY(-50%);
    width: 14px; height: 14px;
    color: var(--muted); pointer-events: none;
}
.admin-table-filter {
    width: 100%;
    padding: .5rem .9rem .5rem 2.1rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .9rem;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.admin-table-filter::placeholder { color: var(--muted); }
.admin-table-filter:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
.admin-table-filter::-webkit-search-cancel-button { -webkit-appearance: none; }
.admin-table-counter {
    flex: 0 0 auto;
    font-size: .75rem; font-weight: 600;
    color: var(--primary-dark);
    background: rgba(201, 162, 39, .18);
    padding: .2rem .55rem;
    border-radius: 999px;
    white-space: nowrap;
}

/* Sortable column headers — chevron indicator on the right.
 *
 * The ⇅ glyph is drawn purely from CSS on every <th> that isn't opted-out
 * with data-no-sort, so it appears at first paint instead of waiting for
 * admin-tables.js to add the .admin-table-sortable class. The JS still
 * adds that class for hover/cursor behaviour and for the active-sort
 * styles (.admin-table-sorted-asc / -desc), but the indicator itself
 * renders without any JS round-trip. Avoids the visible flash of the
 * arrows appearing 1 s after the rest of the table.
 *
 * Scoped to thead > tr:first-child so the search-bar row injected by
 * _table-bar.php (which lives inside thead but has no THs) is unaffected. */
.admin-table:not([data-no-equip]) thead > tr:first-child th:not([data-no-sort]) {
    cursor: pointer; user-select: none; position: relative;
    padding-right: 1.5rem;
}
.admin-table:not([data-no-equip]) thead > tr:first-child th:not([data-no-sort])::after {
    content: '⇅'; position: absolute; right: .5rem; top: 50%;
    transform: translateY(-50%); opacity: .35; font-size: .75rem;
}
/* JS-added classes still drive hover background + active-sort glyph. */
.admin-table-sortable:hover { background: var(--surface-alt); }
.admin-table-sortable.admin-table-sorted-asc::after  { content: '▲'; opacity: 1; color: var(--accent); }
.admin-table-sortable.admin-table-sorted-desc::after { content: '▼'; opacity: 1; color: var(--accent); }

/* Pagination footer — flush against the bottom of the table card. */
.admin-table-pager {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
    padding: .65rem .9rem;
    background: var(--surface);
    border: 1px solid var(--border); border-top: none;
    border-radius: 0 0 var(--radius) var(--radius);
}
.admin-table-pager[hidden] { display: none; }
.admin-table:has(+ .admin-table-pager:not([hidden])) {
    border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.admin-table-pager__btn {
    min-width: 2rem; padding: .35rem .65rem;
    background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .82rem; color: var(--text);
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.admin-table-pager__btn:hover:not(:disabled) {
    background: var(--surface-alt); border-color: var(--accent);
}
.admin-table-pager__btn:disabled { opacity: .35; cursor: not-allowed; }
.admin-table-pager__btn[aria-current="page"] {
    background: var(--primary); border-color: var(--primary); color: var(--bg);
    font-weight: 600;
}
.admin-table-pager__ellipsis { color: var(--muted); padding: 0 .15rem; }

/* Right cluster: passive range info + interactive size selector,
 * styled as two distinct chips so the eye separates "state" from "control". */
.admin-table-pager__right {
    margin-left: auto;
    display: inline-flex; align-items: center; gap: .5rem;
}
.admin-table-pager__info {
    padding: .25rem .65rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 999px;
    font-size: .78rem; color: var(--muted);
    white-space: nowrap;
}
.admin-table-pager__size {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .15rem .55rem .15rem .7rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: .78rem; color: var(--text);
}
.admin-table-pager__size select {
    padding: .15rem .25rem;
    border: none;
    background: transparent; color: var(--text);
    font: inherit; font-size: .82rem; font-weight: 600;
    cursor: pointer;
}
.admin-table-pager__size:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px rgba(201, 162, 39, .25);
}
.admin-table-pager__size select:focus { outline: none; }

/* Clickable rows (any tbody <tr> tagged `data-row-href`).
 * The whole row navigates on click; subtle hover hint signals it. */
tr[data-row-href] { cursor: pointer; transition: background-color .12s ease; }
tr[data-row-href]:hover { background: var(--surface-alt); }
tr[data-row-href]:focus { outline: 2px solid var(--accent); outline-offset: -2px; }

/* === Book palette override (book-form Apparence pane) ===
 * Grid of color rows: round swatch (color picker) + label + hint +
 * source indicator ("Personnalisé" / "Hérité du thème"). The swatch is
 * a styled <input type="color"> so the native picker still opens. */
.palette-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: .65rem;
    margin-top: .25rem;
}
.palette-row {
    display: grid;
    grid-template-columns: 36px 1fr auto;
    align-items: center;
    gap: .85rem;
    padding: .65rem .85rem;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    transition: border-color var(--transition);
}
.palette-row:hover { border-color: var(--accent); }
.palette-row.is-custom { border-color: var(--primary); }
.palette-row__reset {
    width: 1.6rem; height: 1.6rem;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    font-size: .9rem;
    border-radius: 50%;
    cursor: pointer;
    padding: 0;
    margin-left: .25rem;
}
.palette-row__reset:hover { color: var(--primary); border-color: var(--primary); background: var(--surface-alt); }
.palette-row__reset[hidden] { display: none; }
/* Specificity boost via form scope: overrides the form-wide
 * `form input[type=color] { width:60px; height:36px }` rule. */
form .palette-row input[type=color].palette-row__swatch {
    width: 36px; height: 36px;
    padding: 0; border: 1px solid var(--border);
    border-radius: 50%;
    background: var(--surface-alt);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
}
.palette-row__swatch::-webkit-color-swatch-wrapper { padding: 0; border-radius: 50%; }
.palette-row__swatch::-webkit-color-swatch         { border: none; border-radius: 50%; }
.palette-row__swatch::-moz-color-swatch            { border: none; border-radius: 50%; }
.palette-row__text { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.palette-row__label {
    font-size: .9rem; font-weight: 600; color: var(--text);
    line-height: 1.2;
}
.palette-row__hint {
    font-size: .76rem; color: var(--muted);
    line-height: 1.3;
}
.palette-row__source {
    font-size: .7rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted);
    padding: .2rem .55rem;
    background: var(--surface-alt);
    border-radius: 999px;
    white-space: nowrap;
}
.palette-row.is-custom .palette-row__source {
    background: rgba(45, 80, 64, .14);
    color: var(--primary-dark);
}

/* === Genre tag-picker (GitHub-label-style) ===
 * One unified input box: selected genres as removable tags + a search input
 * inline. Suggestions popover below shows existing matches + a "Créer 'x'"
 * fallback when the typed text doesn't match any known genre. */
.genre-picker { position: relative; }
.genre-picker__selected {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
    min-height: 2.4rem;
    padding: .35rem .55rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: text;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.genre-picker__selected:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
.genre-tag {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .15rem .25rem .15rem .65rem;
    background: var(--primary);
    color: var(--bg);
    border-radius: 999px;
    font-size: .82rem; font-weight: 600;
    line-height: 1.4;
}
.genre-tag__remove {
    width: 18px; height: 18px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent;
    border: none; cursor: pointer;
    color: var(--bg);
    font-size: 1rem; line-height: 1;
    border-radius: 50%;
    transition: background var(--transition);
}
.genre-tag__remove:hover { background: rgba(248, 244, 236, .25); }
.genre-picker__input {
    flex: 1; min-width: 140px;
    padding: .25rem .35rem;
    border: none; outline: none; background: transparent;
    font: inherit; font-size: .85rem;
    color: var(--text);
}
.genre-picker__suggestions {
    position: absolute; top: calc(100% + .25rem); left: 0; right: 0;
    z-index: 5;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    max-height: 240px; overflow-y: auto;
    padding: .25rem;
}
.genre-suggestion {
    display: block; width: 100%; text-align: left;
    padding: .45rem .65rem;
    border: none; border-radius: var(--radius-sm);
    background: transparent;
    font: inherit; font-size: .85rem; color: var(--text);
    cursor: pointer;
}
.genre-suggestion:hover, .genre-suggestion:focus {
    background: var(--surface-alt); outline: none;
}
.genre-suggestion--create {
    border-top: 1px solid var(--border-soft);
    margin-top: .25rem; padding-top: .55rem;
    color: var(--accent);
}
.genre-suggestion--create strong { color: var(--primary-dark); }

/* === iOS-style toggle switch === */
.switch {
    display: inline-flex; align-items: center; gap: .5rem;
    cursor: pointer; user-select: none;
}
.switch input {
    position: absolute; opacity: 0; width: 0; height: 0;
    pointer-events: none;
}
.switch__slider {
    position: relative;
    display: inline-block; width: 38px; height: 22px;
    background: var(--border);
    border-radius: 999px;
    transition: background var(--transition);
}
.switch__slider::before {
    content: '';
    position: absolute; top: 2px; left: 2px;
    width: 18px; height: 18px;
    background: var(--surface);
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,.2);
    transition: transform var(--transition);
}
.switch input:checked + .switch__slider {
    background: var(--primary);
}
.switch input:checked + .switch__slider::before {
    transform: translateX(16px);
}
.switch input:focus-visible + .switch__slider {
    outline: 2px solid var(--accent); outline-offset: 2px;
}
.switch__label {
    font-size: .72rem; font-weight: 700;
    letter-spacing: .05em;
    color: var(--muted);
    min-width: 26px;
}
.switch input:checked ~ .switch__label { color: var(--primary-dark); }

/* === Promo row click affordance === */
.promo-row { cursor: pointer; transition: background var(--transition); }
.promo-row:hover { background: var(--surface-alt); }

/* === Promo modal === */
.promo-modal:not([open]) { display: none; }
.promo-modal {
    border: none; padding: 0;
    border-radius: var(--radius-lg);
    background: var(--surface); color: var(--text);
    width: min(640px, calc(100vw - 2rem));
    max-width: none;
    max-height: calc(100vh - 2rem);
    margin: auto;
    box-shadow: 0 28px 80px rgba(27, 58, 42, .35), 0 4px 12px rgba(0,0,0,.08);
    overflow: hidden;
}
.promo-modal[open] { display: flex; flex-direction: column; }
.promo-modal::backdrop {
    background: rgba(27, 58, 42, .55);
    backdrop-filter: blur(4px);
}
.promo-modal__inner {
    display: flex; flex-direction: column;
    overflow-y: auto;
}
.promo-modal__header {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 1.25rem 1.5rem 1rem;
    background: linear-gradient(180deg, var(--surface-alt) 0%, var(--surface) 100%);
    border-bottom: 1px solid var(--border);
}
.promo-modal__header h2 {
    margin: 0; font-size: 1.25rem; color: var(--primary-dark);
}
.promo-modal__header h2 code {
    background: transparent; color: var(--accent);
    font-family: 'SF Mono', monospace; font-size: 1.1rem;
}
.promo-modal__close {
    background: none; border: none;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.1rem; color: var(--muted);
    transition: color var(--transition), background var(--transition);
}
.promo-modal__close:hover { color: var(--primary-dark); background: var(--surface-alt); }
.promo-modal__body { padding: 0 1.5rem 1.5rem; }
.promo-modal__section { padding: 1.25rem 0; border-bottom: 1px solid var(--border-soft); }
.promo-modal__section:last-child { border-bottom: none; }
.promo-modal__section h3 { margin: 0 0 .5rem; font-size: 1rem; color: var(--primary-dark); }
.promo-modal__section--danger h3 { color: var(--danger); }
.promo-modal__hint { font-size: .82rem; color: var(--muted); margin: 0 0 .75rem; line-height: 1.5; }
.promo-modal__row { display: flex; gap: .75rem; align-items: end; flex-wrap: wrap; }
.promo-modal__row label { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: .35rem; font-size: .85rem; color: var(--muted); }
.promo-modal__row input[type=date] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; background: var(--surface);
}
.promo-modal__section--danger label {
    display: flex; flex-direction: column; gap: .35rem;
    font-size: .85rem; color: var(--muted); margin-bottom: .75rem;
}
.promo-modal__section--danger input[type=text] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-family: 'SF Mono', monospace;
}
.promo-modal__section--danger input[type=text]:focus {
    outline: none; border-color: var(--danger);
    box-shadow: 0 0 0 3px rgba(185, 28, 28, .15);
}

/* === Top-books-list cover thumbnails === */
.top-books-list__cover {
    width: 32px; height: 44px;
    border-radius: 3px;
    object-fit: cover;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    flex-shrink: 0;
}
.top-books-list__cover--empty {
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--muted);
}
.top-books-list__cover--empty svg { width: 18px; height: 18px; }

/* === Sales chart card (single dual-series chart on /admin/ventes) === */
.sales-chart-card {
    margin: 0 0 1.5rem; padding: 1.25rem 1.5rem;
    background: var(--surface);
    border: 1px solid var(--border-soft); border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.sales-chart__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    flex-wrap: wrap; gap: 1rem; margin-bottom: .9rem;
}
.sales-chart__heading { margin: 0; font-size: 1.05rem; color: var(--primary-dark); }
.sales-chart__subhead { margin: .15rem 0 0; font-size: .82rem; color: var(--muted); }
.sales-chart__periods { display: inline-flex; gap: .25rem; }
.sales-chart__periods button {
    padding: .35rem .75rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .82rem; font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.sales-chart__periods button:hover { background: var(--surface-alt); border-color: var(--accent); }
.sales-chart__periods button.is-active {
    background: var(--primary); border-color: var(--primary); color: var(--bg);
}
.sales-chart__legend {
    display: flex; gap: 1.5rem; margin-bottom: .5rem;
    flex-wrap: wrap;
}
.sales-chart__series {
    display: inline-flex; align-items: center; gap: .5rem;
    cursor: pointer;
    padding: .35rem .65rem;
    border-radius: var(--radius-sm);
    transition: background var(--transition);
}
.sales-chart__series:hover { background: var(--surface-alt); }
.sales-chart__series input { margin: 0; cursor: pointer; }
.sales-chart__series input:not(:checked) ~ .sales-chart__series-label,
.sales-chart__series input:not(:checked) ~ .sales-chart__series-total {
    text-decoration: line-through; opacity: .45;
}
.sales-chart__swatch {
    display: inline-block; width: 12px; height: 12px; border-radius: 3px;
}
.sales-chart__series--volume  .sales-chart__swatch { background: #2D5040; }
.sales-chart__series--revenue .sales-chart__swatch { background: #C9A227; }
.sales-chart__series-label { font-size: .85rem; color: var(--muted); }
.sales-chart__series-total {
    font-size: .95rem; color: var(--text); font-weight: 700;
}
.sales-chart__plot { position: relative; }
.sales-chart__svg {
    width: 100%; height: auto; max-height: 320px;
    display: block;
    cursor: crosshair;
}
.sales-chart__tooltip {
    position: absolute;
    z-index: 5;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .55rem .75rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12), 0 2px 6px rgba(0, 0, 0, .06);
    font-size: .82rem;
    line-height: 1.45;
    color: var(--text);
    min-width: 160px;
    pointer-events: none;
    transition: opacity .12s ease;
}
.sales-chart__tooltip[hidden] { display: none; }
.sales-chart__tooltip-date {
    font-weight: 600;
    margin-bottom: .35rem;
    color: var(--text);
    font-size: .8rem;
}
.sales-chart__tooltip-row {
    display: flex; align-items: center; gap: .5rem;
    padding: .15rem 0;
}
.sales-chart__tooltip-row strong {
    margin-left: auto;
    font-feature-settings: "tnum";
}
.sales-chart__tooltip-swatch {
    width: 10px; height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}
.sales-chart__tooltip-label { color: var(--muted); font-size: .78rem; }

/* === Export modal — centred via inset:auto + margin:auto on the dialog === */
.export-modal:not([open]) { display: none; }
.export-modal {
    border: none;
    border-radius: 14px;
    padding: 0;
    /* Wider so we can lay out Période + Statut side-by-side on desktop and
     * fit the field grid in 3 columns — eliminates most scrolling. */
    width: min(840px, calc(100vw - 2rem));
    max-width: none;
    max-height: min(85vh, 760px);
    background: var(--surface); color: var(--text);
    box-shadow: 0 30px 70px rgba(27, 58, 42, .4), 0 6px 14px rgba(0, 0, 0, .1);
    margin: auto;
    overflow: hidden;
}
.export-modal[open] { display: flex; flex-direction: column; }
.export-modal::backdrop { background: rgba(27, 58, 42, .55); backdrop-filter: blur(3px); }

/* Native form controls inherit the brand accent (primary green) instead of
 * the OS-default blue, scoped to the modal so it doesn't bleed elsewhere. */
.export-modal,
.export-modal input[type=checkbox],
.export-modal input[type=radio],
.export-modal input[type=date] {
    accent-color: var(--primary);
}

.export-modal__form {
    padding: 0;
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.export-modal__header {
    display: flex; align-items: center; justify-content: space-between;
    padding: .9rem 1.5rem;
    background: var(--primary);
    color: var(--surface);
    flex-shrink: 0;
}
.export-modal__header h2 {
    font-size: 1.05rem; margin: 0;
    color: inherit;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
}
.export-modal__close {
    background: none; border: none; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: inherit;
    padding: 0 .25rem;
    opacity: .85;
    transition: opacity .12s ease;
}
.export-modal__close:hover { opacity: 1; }

/* Body becomes a 2-col grid on desktop: Période + Statut share row 1, the
 * (full-width) Champs à exporter takes row 2. Mobile collapses to 1 col. */
.export-modal__body {
    flex: 1;
    overflow-y: auto;
    padding: 1rem 1.5rem;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem 1.25rem;
    align-items: start;
}
.export-modal__body > fieldset:nth-of-type(3) { grid-column: 1 / -1; }
@media (max-width: 720px) {
    .export-modal__body { grid-template-columns: 1fr; }
}

/* Override the global `form fieldset` chrome (border + cream bg + boxed
 * legend). The modal sections are simple typographic groupings instead. */
form.export-modal__form fieldset,
.export-modal fieldset {
    border: 0;
    border-radius: 0;
    background: transparent;
    padding: 0;
    margin: 0;
}
form.export-modal__form fieldset > legend,
.export-modal fieldset > legend {
    padding: 0;
    margin: 0 0 .55rem;
    background: transparent;
    border: 0;
    border-radius: 0;
    font-size: .68rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .14em;
}

.export-modal__row { display: flex; gap: .75rem; flex-wrap: wrap; }
.export-modal__row label {
    flex: 1; min-width: 130px;
    display: flex; flex-direction: column; gap: .25rem;
    font-size: .68rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .12em;
    font-weight: 600;
}
.export-modal__row input[type=date] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: 8px;
    font: inherit; background: var(--surface);
    color: var(--text);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
}
.export-modal__row input[type=date]:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(45, 80, 64, .12);
}
.export-modal__presets { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .65rem; }
.export-modal__presets .btn {
    padding: .3rem .7rem; font-size: .78rem;
    border-radius: 999px;
}

/* Status radios — stacked vertically inside the Statut column so the modal
 * stays compact, with custom-styled chrome (no boxy native radio). */
.export-modal fieldset > label {
    display: flex; align-items: center; gap: .55rem;
    margin: 0 0 .4rem;
    font-size: .9rem;
    cursor: pointer;
    line-height: 1.3;
}
.export-modal fieldset > label:last-child { margin-bottom: 0; }
.export-modal input[type=checkbox],
.export-modal input[type=radio] {
    width: 1.05rem; height: 1.05rem;
    margin: 0;
    flex-shrink: 0;
}

/* Champs à exporter — 3 cols on desktop to fit all 11 fields without scroll. */
.export-modal__fields {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .35rem 1rem;
}
.export-modal__fields > label {
    margin: 0;
    padding: .25rem 0;
}
@media (max-width: 720px) {
    .export-modal__fields { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
    .export-modal__fields { grid-template-columns: 1fr; }
}

.export-modal__footer {
    display: flex; justify-content: flex-end; gap: .6rem;
    padding: .85rem 1.5rem;
    background: var(--surface-alt, #f7f4ec);
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}
.export-modal__footer .btn-primary {
    min-height: 40px;
    padding: 0 1.25rem;
}

@media (max-width: 600px) {
    .export-modal { max-height: 92vh; border-radius: 12px 12px 0 0; }
}

/* === Status badges (pill display for enum-like status cells) ===
 * Wrap any status with <span class="status-badge status-badge--{slug}">.
 * Colors carry semantic meaning: green = active/positive, gold = pending/
 * in-progress, gray = neutral/archived, red = error/refunded. The slug
 * variants below cover every status enum used in the admin tables. */
.status-badge {
    display: inline-block;
    padding: .22rem .7rem;
    border-radius: 999px;
    font-size: .78rem; font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    background: rgba(0, 0, 0, .06);
    color: var(--muted);
}
/* Green — published, paid, approved, active, sent, read, visible */
.status-badge--published, .status-badge--paid, .status-badge--approved,
.status-badge--active, .status-badge--sent, .status-badge--read,
.status-badge--visible {
    background: rgba(4, 120, 87, .16);
    color: #065f46;
}
/* Gold — preorder, scheduled, pending, new (anticipation) */
.status-badge--preorder, .status-badge--scheduled, .status-badge--pending,
.status-badge--new {
    background: rgba(201, 162, 39, .25);
    color: #7a5e0f;
}
/* Slate-blue — draft (work in progress, not yet ready) */
.status-badge--draft {
    background: rgba(99, 102, 241, .14);
    color: #4338ca;
}
/* Amber — hidden (intentionally pulled but still there) */
.status-badge--hidden, .status-badge--invisible {
    background: rgba(245, 158, 11, .15);
    color: #b45309;
}
/* Gray — archived, unsubscribed, cancelled (cold / decommissioned) */
.status-badge--archived, .status-badge--unsubscribed, .status-badge--cancelled {
    background: rgba(0, 0, 0, .07);
    color: var(--muted);
}
/* Red — error / refunded / rejected / bounced / suspended */
.status-badge--refunded, .status-badge--rejected, .status-badge--bounced,
.status-badge--disputed, .status-badge--suspended {
    background: rgba(220, 38, 38, .12);
    color: #991b1b;
}
/* Generic colour aliases — useful when the badge label is dynamic and
 * doesn't map cleanly to a sematic state above. */
.status-badge--green { background: rgba(4, 120, 87, .16);  color: #065f46; }
.status-badge--gold  { background: rgba(201, 162, 39, .25); color: #7a5e0f; }
.status-badge--red   { background: rgba(220, 38, 38, .12); color: #991b1b; }
.status-badge--gray  { background: rgba(0, 0, 0, .07);     color: var(--muted); }

@media (max-width: 640px) {
    .admin-table-bar { flex-wrap: wrap; }
    .admin-table-counter { order: 2; margin-left: auto; }
    .admin-table-pager__info { width: 100%; margin-left: 0; text-align: center; }
}
.muted { color: var(--muted); }
small { color: var(--muted); }

/* === Header / nav === */
.admin-header {
    display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
    padding: 1rem 1.75rem;
    background: var(--primary);
    color: var(--bg);
    box-shadow: var(--shadow-sm);
    position: sticky; top: 0; z-index: 10;
}
.admin-header a { color: var(--bg); text-decoration: none; }
.admin-header .admin-brand {
    display: inline-flex;
    align-items: center;
    gap: .65rem;
    font-family: 'Cinzel', serif;
    font-size: 1.2rem; font-weight: 600;
    letter-spacing: .02em; padding-right: 1rem;
    border-right: 1px solid rgba(248, 244, 236, .15);
    margin-right: .25rem;
    color: var(--accent);
}
.admin-brand__mark {
    width: 32px; height: 32px;
    display: block;
    flex-shrink: 0;
}
.admin-brand__text { line-height: 1; }
.admin-header .admin-brand:hover { color: var(--bg); }
.admin-header .admin-brand:hover .admin-brand__mark { transform: scale(1.04); }
.admin-brand__mark { transition: transform .15s ease; }
@media (max-width: 600px) {
    .admin-brand__text { display: none; }
    .admin-header .admin-brand { padding-right: 0; border-right: 0; margin-right: 0; }
}
.admin-nav { flex: 1; display: flex; gap: .25rem; flex-wrap: wrap; }
.admin-nav a {
    padding: .5rem .9rem; border-radius: var(--radius-sm);
    font-size: .9rem; opacity: .85;
    transition: background var(--transition), opacity var(--transition), color var(--transition);
}
.admin-nav a:hover { opacity: 1; background: rgba(248, 244, 236, .08); color: var(--bg); }
/* Header badge — small pill next to a nav link when there's pending
 * work (unmoderated reviews, unread messages, ambassadors owed money). */
.admin-nav a { position: relative; }
.admin-nav__badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px;
    margin-left: .4rem;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--primary-dark);
    font-size: .68rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0;
    vertical-align: 1px;
}
.admin-nav a[aria-current="page"] {
    color: var(--primary-dark); background: var(--accent);
    opacity: 1; font-weight: 600;
}

/* === Mobile burger — ambassador portal header (layouts/ambassador.php) ===
 * Desktop: the burger is hidden and .amb-menu is display:contents, so the
 * nav + logout lay out as direct header flex children (desktop bar unchanged).
 * Mobile (≤768px, see the media query further down): the burger appears and
 * toggles the collapsed .amb-menu panel. */
.amb-menu { display: contents; }
.amb-burger {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 42px; height: 42px;
    padding: 0;
    border: 1px solid rgba(201, 162, 39, .55);
    border-radius: var(--radius-sm);
    background: transparent;
    cursor: pointer;
}
.amb-burger__bar {
    display: block;
    width: 20px; height: 2px;
    margin: 0 auto;
    background: var(--accent);
    transition: transform .2s ease, opacity .15s ease;
}
.amb-burger[aria-expanded="true"] .amb-burger__bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.amb-burger[aria-expanded="true"] .amb-burger__bar:nth-child(2) { opacity: 0; }
.amb-burger[aria-expanded="true"] .amb-burger__bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.admin-logout {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .45rem .9rem;
    border: 1px solid rgba(201, 162, 39, .55);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--accent) !important;
    font-size: .85rem; font-weight: 600;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.admin-logout svg { width: 16px; height: 16px; }
.admin-logout:hover {
    background: var(--accent);
    color: var(--primary-dark) !important;
    border-color: var(--accent);
}

/* === Header notification bell ==========================================
 * A bell button in the admin header with an unread-count badge; clicking
 * it drops a panel listing recent notifications. Each entry links to the
 * relevant admin page (NotificationsController marks it read en route). */
.admin-bell { position: relative; display: inline-flex; }
.admin-bell__btn {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px;
    border: 1px solid rgba(201, 162, 39, .55);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--accent);
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.admin-bell__btn svg { width: 18px; height: 18px; }
.admin-bell__btn:hover { background: var(--accent); color: var(--primary-dark); }
.admin-bell__badge {
    position: absolute; top: -6px; right: -6px;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--danger, #b94a48);
    color: #fff;
    font-size: .68rem; font-weight: 700; line-height: 1;
}
.admin-bell__panel {
    position: absolute; top: calc(100% + 8px); right: 0;
    width: 340px; max-width: calc(100vw - 2rem);
    background: var(--surface, #fff);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
    z-index: 50;
    overflow: hidden;
}
.admin-bell__panel[hidden] { display: none; }
.admin-bell__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: .5rem;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--border);
    font-size: .95rem;
}
.admin-bell__readall-form { margin: 0; }
.admin-bell__readall {
    border: 0; background: transparent;
    color: var(--primary);
    font-size: .8rem; cursor: pointer;
    padding: 0; text-decoration: underline;
}
.admin-bell__empty {
    margin: 0; padding: 1.25rem .9rem;
    color: var(--muted); font-size: .88rem; text-align: center;
}
.admin-bell__list {
    list-style: none; margin: 0; padding: 0;
    max-height: 380px; overflow-y: auto;
}
.admin-bell__item { border-bottom: 1px solid var(--border-soft, rgba(0, 0, 0, .06)); }
.admin-bell__item:last-child { border-bottom: 0; }
.admin-bell__item a {
    display: block;
    padding: .7rem .9rem;
    color: var(--text) !important;
    text-decoration: none;
    transition: background var(--transition);
}
.admin-bell__item a:hover { background: var(--surface-alt, rgba(0, 0, 0, .03)); }
.admin-bell__item.is-unread a { background: rgba(201, 162, 39, .1); }
.admin-bell__item.is-unread a:hover { background: rgba(201, 162, 39, .16); }
.admin-bell__item-title {
    display: block; font-weight: 600; font-size: .88rem;
    margin-bottom: .15rem;
}
.admin-bell__item-body {
    display: block; font-size: .82rem; color: var(--muted); line-height: 1.4;
}
.admin-bell__item-time {
    display: block; margin-top: .3rem;
    font-size: .72rem; color: var(--muted);
}
@media (max-width: 600px) {
    .admin-bell__panel {
        position: fixed; top: 64px; right: 1rem; left: 1rem; width: auto;
    }
}

/* === Main === */
.admin-main { max-width: 1280px; margin: 2.5rem auto; padding: 0 1.75rem; }
.admin-main > header {
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem;
    margin-bottom: 1.5rem;
}
.admin-main > header h1 { margin-bottom: 0; }

/* === Buttons === */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    padding: .55rem 1.1rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit; font-size: .9rem; font-weight: 500;
    cursor: pointer; text-decoration: none;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
}
.btn:hover { background: var(--surface-alt); border-color: var(--accent); transform: translateY(-1px); }
.btn-primary {
    background: var(--primary); color: var(--bg); border-color: var(--primary);
    font-weight: 600;
}
.btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: var(--bg); }
.btn-danger { background: var(--danger); color: white; border-color: var(--danger); font-weight: 600; }
.btn-danger:hover { background: #991b1b; border-color: #991b1b; color: white; }
.btn-secondary { background: var(--surface-alt); border-color: var(--border); }
.btn:disabled, .btn[disabled] {
    opacity: .5;
    cursor: not-allowed;
    transform: none;
    pointer-events: none;
}

/* === Sections / cards === */
.section {
    background: var(--surface);
    padding: 1.75rem;
    border-radius: var(--radius);
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
}
.section h2 {
    margin-top: 0; margin-bottom: 1.25rem;
    padding-bottom: .75rem; border-bottom: 1px solid var(--border-soft);
}

/* === KPI grid === */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
    margin-bottom: 2rem;
}
.kpi {
    display: block; text-decoration: none;
    background: var(--surface);
    padding: 1.5rem 1.75rem;
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    border-left: 4px solid var(--accent);
    transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
    cursor: pointer;
}
.kpi:hover {
    transform: translateY(-2px); box-shadow: var(--shadow);
    border-color: var(--accent);
}
.kpi-label {
    font-size: .8rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--muted); font-weight: 600;
    margin-bottom: .35rem;
}
.kpi-value {
    font-family: 'Cinzel', serif;
    font-size: 2.25rem; font-weight: 700; line-height: 1;
    color: var(--primary);
    margin: 0 0 .5rem;
}
.kpi-foot {
    margin: 0; font-size: .78rem; color: var(--accent); font-weight: 600;
}
.kpi:hover .kpi-foot { color: var(--primary-dark); }

/* === Tables === */
table {
    width: 100%; border-collapse: separate; border-spacing: 0;
    background: var(--surface);
    border-radius: var(--radius); overflow: hidden;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
}
table thead th {
    background: var(--primary);
    padding: .8rem 1rem;
    text-align: left;
    font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--bg); font-weight: 600;
    border-bottom: 1px solid var(--primary-dark);
}
/* Sortable header indicators in green-bg context: full-opacity cream
 * by default, gold when actively sorted. Targets the same paint-time
 * selector as the base rule above (no JS-added class needed for the
 * default chevron). */
table:not([data-no-equip]) thead > tr:first-child th:not([data-no-sort])::after { color: var(--bg); opacity: .55; }
table thead th.admin-table-sortable:hover { background: var(--primary-dark); }
table thead th.admin-table-sortable.admin-table-sorted-asc::after,
table thead th.admin-table-sortable.admin-table-sorted-desc::after { color: var(--accent); opacity: 1; }
table tbody td {
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--border-soft);
    font-size: .92rem;
    vertical-align: middle;
}
table tbody tr:last-child td { border-bottom: none; }
table tbody tr:hover { background: var(--surface-alt); }
table tbody tr td[colspan] { text-align: center; color: var(--muted); padding: 2rem; font-style: italic; }
.section table { box-shadow: none; border-radius: var(--radius-sm); }

/* === Forms === */
form label { display: block; margin: 1rem 0; font-size: .9rem; font-weight: 500; color: var(--text); }
/* The HTML5 `hidden` attribute must always win over the form-label display rule
 * above (same specificity, declaration order matters). */
form label[hidden] { display: none; }
form fieldset {
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    padding: 1.25rem 1.5rem 1rem;
    margin-bottom: 1.5rem;
    background: var(--surface-alt);
}
form fieldset > legend {
    padding: 0 .65rem;
    font-size: .85rem; font-weight: 600;
    color: var(--primary-dark);
    letter-spacing: .03em;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
}
form fieldset > label:first-of-type { margin-top: .5rem; }

form input[type=text], form input[type=email], form input[type=password],
form input[type=number], form input[type=date], form input[type=datetime-local],
form input[type=url], form input[type=search], form input[type=tel],
form select, form textarea {
    width: 100%; padding: .55rem .8rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .92rem;
    background: var(--surface); color: var(--text);
    transition: border-color var(--transition), box-shadow var(--transition);
}
form input:disabled, form select:disabled, form textarea:disabled {
    background: var(--surface-alt);
    color: var(--muted);
    border-color: var(--border-soft, var(--border));
    cursor: not-allowed;
    opacity: .8;
}
form input:focus, form select:focus, form textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
form textarea { resize: vertical; min-height: 100px; font-family: inherit; }

/* Selects: drop the native OS widget (its own chevron + box style clashed
 * with the site's inputs) and draw a discreet chevron in-house, so a
 * <select> reads exactly like a text field. */
form select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 2.25rem;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6' fill='none' stroke='%236f6f66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .85rem center;
    background-size: .72rem auto;
}
form input[type=checkbox], form input[type=radio] { width: auto; margin-right: .35rem; }
form input[type=color] { width: 60px; height: 36px; padding: 2px; cursor: pointer; }
form input[type=file] {
    width: 100%; padding: .5rem; border: 1px dashed var(--border);
    border-radius: var(--radius-sm); background: var(--surface);
    cursor: pointer; font-size: .9rem;
}
form input[type=file]:hover { border-color: var(--accent); }

form details {
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    padding: .85rem 1.25rem;
    margin-bottom: 1rem;
    transition: box-shadow var(--transition);
}
form details[open] { box-shadow: var(--shadow-sm); }
form details summary {
    cursor: pointer; font-weight: 600; color: var(--primary-dark);
    padding: .25rem 0;
}
form details summary:hover { color: var(--accent); }
form details > * + * { margin-top: .75rem; }

/* === Auth pages (login, totp-enroll, totp-recovery, totp-challenge) === */
.admin-login, .admin-totp, .admin-recovery {
    max-width: 460px; margin: 4rem auto;
    background: var(--surface);
    padding: 2.5rem;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--border-soft);
}
.admin-login h1, .admin-totp h1, .admin-recovery h1 { text-align: center; margin-bottom: 1.5rem; }
.admin-login h1::after, .admin-totp h1::after, .admin-recovery h1::after { margin-left: auto; margin-right: auto; }
.admin-totp p, .admin-recovery p { color: var(--muted); line-height: 1.7; }
.admin-totp img { margin: 1.5rem auto; border-radius: var(--radius); border: 1px solid var(--border); padding: .5rem; background: var(--surface); }
.admin-totp code {
    display: block; text-align: center;
    margin: 1rem 0; padding: 1rem;
    font-size: 1.1rem; letter-spacing: .15em;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--radius-sm); color: var(--primary-dark);
    word-break: break-all;
}
.admin-recovery ul {
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 1.25rem 2rem;
    list-style: none;
    columns: 2; column-gap: 2rem;
}
.admin-recovery li {
    padding: .35rem 0; font-family: 'SF Mono', Menlo, monospace;
    font-size: 1rem; letter-spacing: .05em; color: var(--primary-dark);
    break-inside: avoid;
}

/* === Flash messages === */
.flash {
    padding: .85rem 1.25rem; border-radius: var(--radius-sm);
    margin: 1rem 0; font-size: .9rem;
    border: 1px solid transparent;
}
.flash-error { background: var(--danger-soft); color: var(--danger); border-color: #fecaca; }
.flash-success { background: var(--success-soft); color: var(--success); border-color: #bbf7d0; }

/* === Mobile === */
@media (max-width: 768px) {
    .admin-header { padding: .75rem 1rem; }
    .admin-brand { padding-right: 0; border-right: none; margin-right: 0; }
    /* Nav drops to its own full-width row under the brand. `flex-basis`
       (not just `width`) is required: the base `.admin-nav{flex:1}` sets
       flex-basis:0, which would otherwise win and keep the nav inline. */
    .admin-nav {
        flex-basis: 100%;
        gap: .3rem;
        overflow-x: auto;
        flex-wrap: nowrap;
        padding-bottom: .25rem;
    }
    .admin-nav a { white-space: nowrap; padding: .4rem .75rem; font-size: .85rem; }

    /* Ambassador portal + admin: the nav collapses behind a burger button. */
    body.ambassador .amb-burger,
    body.admin .amb-burger { display: flex; margin-left: auto; }
    body.ambassador .amb-menu,
    body.admin .amb-menu {
        display: none;
        flex-basis: 100%;
        flex-direction: column;
        gap: .3rem;
        margin-top: .55rem;
    }
    body.ambassador .amb-menu.is-open,
    body.admin .amb-menu.is-open { display: flex; }
    body.ambassador .amb-menu .admin-nav,
    body.admin .amb-menu .admin-nav {
        flex: 0 0 auto;
        flex-direction: column;
        flex-wrap: nowrap;
        overflow: visible;
        gap: .15rem;
        width: 100%;
        padding-bottom: 0;
    }
    body.ambassador .amb-menu .admin-nav a,
    body.admin .amb-menu .admin-nav a {
        padding: .7rem .9rem;
        font-size: .95rem;
    }
    body.ambassador .amb-menu .admin-logout,
    body.admin .amb-menu .admin-logout {
        margin: .35rem 0 0;
        justify-content: center;
    }
    /* Admin-only header extras inside the collapsed menu (bell)
       — give them room and left-align like the nav links. */
    body.admin .amb-menu .admin-bell { margin: .35rem 0 0; }
    .admin-main { margin: 1.5rem auto; padding: 0 1rem; }
    .kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .kpi { padding: 1.25rem; }
    .kpi-value { font-size: 1.75rem; }
    table { font-size: .85rem; }
    table thead th, table tbody td { padding: .6rem .75rem; }
    .section { padding: 1.25rem; }
    .admin-main > header { flex-direction: column; align-items: stretch; }
    .admin-recovery ul { columns: 1; }

    /* === Ergonomie mobile globale (passe responsive admin) ================
     * Corrige d'un coup les constats transverses de l'audit par page :
     * cibles tactiles, zoom iOS, et chaînes insécables qui débordent. */
    body.admin .btn,
    body.admin .admin-logout { min-height: 44px; }
    /* iOS Safari zoome au focus dès qu'un champ est < 16px. */
    body.admin form input:not([type="checkbox"]):not([type="radio"]):not([type="color"]),
    body.admin form select,
    body.admin form textarea { font-size: 16px; }
    /* Emails, IDs Stripe, URLs, JSON… : casser au lieu de pousser la page. */
    body.admin .section a[href^="mailto:"],
    body.admin .section code,
    body.admin .section pre { overflow-wrap: anywhere; word-break: break-word; }
    /* Filet anti-débordement résiduel : absorbe les quelques px de slop (padding,
       éléments sr-only…). `clip` (≠ hidden) ne crée pas de conteneur de scroll,
       donc le scroll interne des .admin-table et le défilement vertical sont
       intacts. */
    body.admin .admin-main { overflow-x: clip; }

    /* Wide data tables (factures, codes, ventes…) scroll sideways INSIDE their
       .admin-table-wrap (added by admin-tables.js) instead of overflowing the
       page. The table stays display:table + width:100% so a narrow/empty table
       fills its column — no dead gutter on the right. The pager is inserted
       after the wrap, so it stays full-width and doesn't scroll with it. */
    body.ambassador .admin-table,
    body.admin .admin-table { width: 100%; }
    body.ambassador .admin-table th,
    body.ambassador .admin-table td,
    body.admin .admin-table th,
    body.admin .admin-table td { white-space: nowrap; }
    body.ambassador .ambassador-dashboard__month-table { table-layout: auto; }

    /* "Mes codes" embeds the share-link block (form content, not pure data) —
       a horizontal-scroll table mangles it. Stack it into cards instead,
       overriding the generic scroll rule above. */
    /* This table is restyled into stacked cards (block rows), so it must stay
       display:block — otherwise the default display:table would wrap the block
       rows in anonymous table boxes and break the card layout. */
    body.ambassador .ambassador-codes__table { display: block; overflow-x: visible; }
    body.ambassador .ambassador-codes__table thead { display: none; }
    body.ambassador .ambassador-codes__table tbody,
    body.ambassador .ambassador-codes__table tr,
    body.ambassador .ambassador-codes__table td { display: block; width: auto; }
    body.ambassador .ambassador-codes__table td { white-space: normal; }
    body.ambassador .ambassador-codes__table tr:not(.ambassador-codes__link-row) {
        border: 1px solid var(--border);
        border-radius: var(--radius, 8px);
        padding: .55rem .8rem;
        margin-bottom: .5rem;
    }
    body.ambassador .ambassador-codes__table tr:not(.ambassador-codes__link-row) td {
        padding: .15rem 0;
    }
    body.ambassador .ambassador-codes__table .ambassador-codes__link-row td { padding: 0; }
}

/* === Admin — très petits écrans (≤480px) : grilles KPI en 1 colonne ===== */
@media (max-width: 480px) {
    body.admin .kpi-grid,
    body.admin .ambassador-detail__kpi-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Dashboard widgets (added in migration 0013)
   ============================================================ */

/* ── Charts row ── */
.dashboard-charts {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    margin-bottom: 1.5rem;
}
@media (max-width: 720px) {
    .dashboard-charts { grid-template-columns: 1fr; }
}

.dashboard-chart-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    padding: 1.1rem 1.25rem 1rem;
    box-shadow: var(--shadow-sm);
    /* button reset */
    font: inherit;
    text-align: left;
    color: inherit;
    width: 100%;
    cursor: pointer;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.dashboard-chart-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0,0,0,.1);
    border-color: var(--accent);
}
.dashboard-chart-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.dashboard-chart-card__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .75rem;
}
.dashboard-chart-card__title {
    font-family: 'Cinzel', Georgia, serif;
    font-size: .95rem;
    color: var(--primary-dark);
    margin: 0;
}
.dashboard-chart-card__meta {
    font-size: .8rem;
    font-weight: 600;
    color: var(--muted);
    white-space: nowrap;
}
.dashboard-chart-card__subtitle {
    margin: .15rem 0 0;
    font-size: .77rem;
    color: var(--muted);
    font-style: italic;
    font-weight: 400;
}

/* ── Insights row ── */
.dashboard-insights {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}
@media (max-width: 900px) {
    .dashboard-insights { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 580px) {
    .dashboard-insights { grid-template-columns: 1fr; }
}

/* ── Generic dashboard card ── */
.dashboard-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    padding: 1.25rem;
    box-shadow: var(--shadow-sm);
    min-width: 0; /* grid item: allow shrinking so list rows ellipsize on mobile */
}
.dashboard-card h3 {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1rem;
    color: var(--primary);
    margin: 0 0 .85rem;
    padding-bottom: .55rem;
    border-bottom: 1px solid var(--border-soft);
}

/* ── Bottom row ── */
.dashboard-bottom {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    margin-bottom: 2rem;
    align-items: start;
}
.dashboard-bottom .alltime-card {
    display: flex; flex-direction: column;
    max-height: 220px;
}
.dashboard-bottom .alltime-card .alltime-card__metrics {
    flex: 1;
    align-content: center;
}
@media (max-width: 720px) {
    .dashboard-bottom { grid-template-columns: 1fr; }
}

/* ── Top books list ── */
.top-books-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.top-books-list__row {
    display: flex;
    align-items: center;
    gap: .75rem;
}
.top-books-list__rank {
    font-family: 'Cinzel', Georgia, serif;
    font-size: .8rem;
    font-weight: 700;
    color: var(--accent);
    min-width: 1.2rem;
    flex-shrink: 0;
}
.top-books-list__title {
    flex: 1;
    font-size: .9rem;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.top-books-list__title:hover { color: var(--accent); }
.top-books-list__stats {
    font-size: .78rem;
    color: var(--muted);
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── Rating display ── */
.rating-display {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    padding: .5rem 0;
    text-align: center;
}
.rating-display__stars {
    font-size: 1.85rem;
    line-height: 1;
    letter-spacing: .05em;
}
.star--full  { color: var(--accent); }
.star--half  { color: var(--accent); opacity: .65; }
.star--empty { color: var(--border); }
.rating-display__score {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--primary);
    margin: 0;
}
.rating-display__count {
    font-size: .82rem;
    color: var(--muted);
    margin: 0;
}
.rating-display__count a {
    color: var(--muted);
    text-decoration: none;
}
.rating-display__count a:hover { color: var(--accent); }

/* ── Action list ── */
.action-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .25rem;
}
.action-list li a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .55rem .75rem;
    border-radius: var(--radius-sm);
    background: rgba(201, 162, 39, .06);
    border: 1px solid rgba(201, 162, 39, .18);
    font-size: .88rem;
    color: var(--text);
    text-decoration: none;
    transition: background var(--transition), border-color var(--transition);
}
.action-list li a:hover {
    background: rgba(201, 162, 39, .14);
    border-color: var(--accent);
}
.action-list__arrow {
    color: var(--accent);
    font-weight: 700;
    flex-shrink: 0;
}

/* ── Preorders list ── */
.preorders-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.preorders-list__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}
.preorders-list__info {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    min-width: 0;
}
.preorders-list__info a {
    font-size: .9rem;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.preorders-list__info a:hover { color: var(--accent); }
.preorders-list__badge {
    font-size: .75rem;
    font-weight: 600;
    padding: .2rem .6rem;
    border-radius: var(--radius-pill);
    background: rgba(201, 162, 39, .18);
    color: #7a5e0f;
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── All-time card — inline summary stats (intentionally distinct from
 *    the top KPI grid: no card-in-card, no border-left, just icon +
 *    value + label in a row with thin gold dividers between metrics). ── */
.alltime-card__metrics {
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-wrap: wrap;
    align-items: center; gap: 0;
}
.alltime-card__metric {
    flex: 1; min-width: 160px;
    display: flex; align-items: center; gap: .75rem;
    padding: .25rem 1.25rem;
    border-right: 1px solid rgba(201, 162, 39, .35);
}
.alltime-card__metric:last-child { border-right: none; }
.alltime-card__metric svg {
    width: 28px; height: 28px;
    color: var(--accent);
    flex-shrink: 0;
}
.alltime-card__value {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.45rem; font-weight: 700; line-height: 1;
    color: var(--primary-dark);
    display: block;
}
.alltime-card__label {
    font-size: .72rem; letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted); font-weight: 600;
    margin-top: .15rem;
    display: block;
}
.alltime-card__text {
    display: flex; flex-direction: column;
    line-height: 1.1;
}
@media (max-width: 720px) {
    /* Drop the desktop height cap: with flex-wrap it made the 3 metrics wrap
       into 2 columns and align-content:center shoved them to the middle,
       leaving a big empty gutter. Let the card grow and stack cleanly. */
    .dashboard-bottom .alltime-card { max-height: none; }
    .dashboard-bottom .alltime-card .alltime-card__metrics {
        flex-direction: column; flex-wrap: nowrap;
        align-items: stretch; align-content: normal;
    }
    .alltime-card__metric { border-right: none; border-bottom: 1px solid rgba(201, 162, 39, .25); padding: .75rem 0; }
    .alltime-card__metric:last-child { border-bottom: none; }
}

/* ── Chart expand modal ─────────────────────────────────────────────────── */
.chart-modal:not([open]) { display: none; }
.chart-modal {
    border: none; padding: 0;
    border-radius: var(--radius-lg);
    background: var(--surface); color: var(--text);
    width: min(1100px, calc(100vw - 3rem));
    max-width: none;
    max-height: calc(100vh - 3rem);
    box-shadow: 0 28px 80px rgba(27, 58, 42, .35), 0 4px 12px rgba(0,0,0,.08);
    overflow: hidden;
    margin: auto; /* explicit centering — UA default but cemented */
}
.chart-modal[open] {
    display: flex; flex-direction: column;
}
.chart-modal::backdrop {
    background: rgba(27, 58, 42, .55);
    backdrop-filter: blur(4px);
}
.chart-modal__inner {
    display: flex; flex-direction: column;
    overflow-y: auto;
}

/* ── Header — title with gold accent underline, like dashboard h1 ───── */
.chart-modal__header {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 1.25rem 1.75rem 1rem;
    background: linear-gradient(180deg, var(--surface-alt) 0%, var(--surface) 100%);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.chart-modal__title {
    margin: 0;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.4rem;
    color: var(--primary-dark);
    letter-spacing: -.005em;
}
.chart-modal__title::after {
    content: ''; display: block;
    width: 36px; height: 2px;
    background: var(--accent);
    margin-top: .55rem;
}
.chart-modal__close {
    background: none; border: none;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.1rem; line-height: 1;
    color: var(--muted);
    transition: color var(--transition), background var(--transition);
}
.chart-modal__close:hover { color: var(--primary-dark); background: var(--surface-alt); }

/* ── Controls — chips group + date range ──────────────────────────────── */
.chart-modal__controls {
    display: flex; align-items: center;
    flex-wrap: wrap; gap: 1rem 1.5rem;
    padding: .9rem 1.75rem;
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.chart-modal__chips {
    display: inline-flex; gap: .25rem;
    background: var(--surface);
    padding: .25rem;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-soft);
}
.chart-modal__chip {
    padding: .4rem .85rem;
    border: none; border-radius: var(--radius-pill);
    background: transparent;
    color: var(--muted);
    font: inherit; font-size: .82rem; font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.chart-modal__chip:hover { color: var(--primary-dark); background: var(--surface-alt); }
.chart-modal__chip.is-active {
    background: var(--primary);
    color: var(--bg);
    box-shadow: 0 1px 3px rgba(45, 80, 64, .3);
}
.chart-modal__range {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}
.chart-modal__range-label {
    display: inline-flex; align-items: center; gap: .4rem;
    font-size: .8rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .05em;
}
.chart-modal__date-input {
    padding: .35rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .85rem;
    cursor: pointer;
}
.chart-modal__date-input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}

/* ── Chart plot wrapper hosts the SVG and the absolutely-positioned
 *    tooltip, mirroring the .sales-chart__plot pattern. ──────────────── */
.chart-modal__plot {
    position: relative;
    flex: 1 1 auto;
    background: var(--surface);
    padding: 1.5rem 1.75rem .5rem;
}
.chart-modal__svg {
    display: block;
    width: 100%;
    min-height: 280px; max-height: 460px;
    cursor: crosshair;
}
.chart-modal__tooltip {
    position: absolute;
    z-index: 5;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .55rem .75rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12), 0 2px 6px rgba(0, 0, 0, .06);
    font-size: .82rem;
    line-height: 1.45;
    color: var(--text);
    min-width: 160px;
    pointer-events: none;
    transition: opacity .12s ease;
}
.chart-modal__tooltip[hidden] { display: none; }
.chart-modal__tooltip-date {
    font-weight: 600;
    margin-bottom: .35rem;
    font-size: .8rem;
}
.chart-modal__tooltip-row {
    display: flex; align-items: center; gap: .5rem;
}
.chart-modal__tooltip-row strong {
    margin-left: auto;
    font-feature-settings: "tnum";
}
.chart-modal__tooltip-swatch {
    width: 10px; height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}
.chart-modal__tooltip-label { color: var(--muted); font-size: .78rem; }

/* ── Summary footer — gold-tinted info bar with the period span ─────── */
.chart-modal__summary {
    padding: .85rem 1.75rem 1rem;
    margin: 0;
    background: linear-gradient(0deg, var(--surface-alt) 0%, var(--surface) 100%);
    border-top: 1px solid var(--border);
    font-size: .85rem; color: var(--text);
    text-align: center;
    flex-shrink: 0;
}
@media (max-width: 600px) {
    .chart-modal {
        width: calc(100vw - 1rem);
        max-height: calc(100vh - 1rem);
        border-radius: var(--radius);
    }
    .chart-modal__header { padding: 1rem 1.1rem .85rem; }
    .chart-modal__title { font-size: 1.15rem; }
    .chart-modal__controls { padding: .75rem 1.1rem; gap: .75rem; }
    .chart-modal__plot { padding: 1rem 1.1rem 0; }
    .chart-modal__svg { min-height: 220px; }
    .chart-modal__summary { padding: .75rem 1.1rem 1rem; }
}

/* ============================================================
   Settings page — tabbed 2-column layout
   ============================================================ */

/* Two-column grid: fixed left rail + fluid right content area. */
.settings-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 1.5rem;
    align-items: start;
}
/* Grid items default to min-width:auto, which refuses to shrink below their
   content's min-content — on mobile (single 1fr column) that lets the form
   track balloon past the viewport. Force them to shrink so panes wrap. */
.settings-layout > nav,
.settings-layout > form { min-width: 0; }
/* <fieldset> carries an implicit `min-width: min-content` from the UA
   stylesheet that block-level `width` can't override — on mobile it refuses
   to shrink and forces horizontal overflow. Reset it everywhere in admin. */
body.admin fieldset { min-width: 0; }
/* Right column wrapper: lets the book form host extra standalone <form>
 * elements (file uploads, archive) inside the same column without
 * breaking the 2-col grid. Stacks them vertically. */
.settings-content {
    display: flex; flex-direction: column; gap: 1rem;
    min-width: 0;
}

/* ── Left rail ── */
.settings-tabs {
    position: sticky;
    top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}

/* ── Individual tab button ── */
.settings-tab {
    /* button reset */
    appearance: none;
    -webkit-appearance: none;
    border: none;
    background: none;
    margin: 0;
    font: inherit;
    /* layout */
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .6rem .85rem;
    border-radius: var(--radius-sm);
    width: 100%;
    text-align: left;
    font-size: .9rem;
    color: var(--text);
    cursor: pointer;
    transition: background .15s;
}
.settings-tab:hover { background: var(--surface-alt); }
.settings-tab.is-active {
    background: var(--primary);
    color: var(--bg);
}

/* ── Tab icon ── */
.settings-tab svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--tab-accent, var(--muted));
}
.settings-tab.is-active svg { color: var(--bg); }

/* ── Per-accent color variants (icon color when tab is NOT active) ── */
.settings-tab[data-accent="green"]  { --tab-accent: var(--primary); }
.settings-tab[data-accent="gray"]   { --tab-accent: var(--muted); }
.settings-tab[data-accent="gold"]   { --tab-accent: var(--accent); }
.settings-tab[data-accent="blue"]   { --tab-accent: #3b82f6; }
.settings-tab[data-accent="red"]    { --tab-accent: #ef4444; }
.settings-tab[data-accent="purple"] { --tab-accent: #8b5cf6; }
.settings-tab[data-accent="teal"]   { --tab-accent: #14b8a6; }
.settings-tab[data-accent="orange"] { --tab-accent: #f97316; }

/* ── Content panes ── */
.settings-pane {
    display: none;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    padding: 1.75rem;
    box-shadow: var(--shadow-sm);
}
.settings-pane.is-active { display: block; }

/* Spacing for direct children that are form controls / sections. */
.settings-pane > fieldset,
.settings-pane > .field,
.settings-pane > label {
    margin-bottom: 1.25rem;
}

/* ── Action buttons stack at the bottom of the rail ── */
.settings-actions {
    display: flex; flex-direction: column; gap: .5rem;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border-soft);
}
.settings-actions__btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: .5rem;
    width: 100%;
}
.settings-actions__btn svg { width: 16px; height: 16px; flex-shrink: 0; }
/* Disabled save button — applies to every settings-style form (book,
 * settings, promo) via the shared `.is-disabled` class plus the native
 * `:disabled` attribute on the legacy settings.php form. */
#settings-save:disabled,
.settings-actions__btn.is-disabled,
.settings-actions__btn[aria-disabled="true"] {
    background: var(--surface-alt) !important;
    color: var(--muted) !important;
    border-color: var(--border) !important;
    cursor: not-allowed;
    opacity: 1;
}
#settings-save:disabled:hover,
.settings-actions__btn.is-disabled:hover,
.settings-actions__btn[aria-disabled="true"]:hover {
    background: var(--surface-alt) !important;
    color: var(--muted) !important;
    transform: none;
}

/* ── Mobile: stack layout + horizontal scroll rail ──
   768px to match the admin burger-nav breakpoint (was 720, which left a
   721–768px dead zone where the burger showed but settings stayed 2-col). */
@media (max-width: 768px) {
    .settings-layout {
        grid-template-columns: 1fr;
    }
    .settings-tabs {
        position: static;
        flex-direction: row;
        flex-wrap: wrap;          /* tabs wrap to 2 rows — all visible, no hidden scroll */
        gap: .4rem;
        padding: .7rem .85rem;
    }
    .settings-tab {
        width: auto;              /* override the 100% from the vertical-rail base rule */
        flex: 0 1 auto;
        white-space: nowrap;
        padding: .5rem .8rem;
        font-size: .84rem;
    }
    /* Save button breaks onto its own full-width row below the tab strip. */
    .settings-actions {
        flex-basis: 100%;
        margin-top: .35rem;
        padding-top: .7rem;
    }
}

/* === Font picker: live preview card (book-form apparence pane) === */
.font-preview {
    padding: 1rem;
    border-radius: var(--radius);
    border: 1px solid var(--border-soft);
    background: var(--surface);
    margin-top: 1rem;
}
.font-preview__heading {
    font-family: var(--font-display-preview, inherit);
    font-size: 1.5rem;
    color: var(--primary-dark);
    margin-bottom: .5rem;
    line-height: 1.2;
}
.font-preview__body {
    font-family: var(--font-body-preview, inherit);
    font-size: 1rem;
    color: var(--text);
    line-height: 1.6;
    max-width: 65ch;
}

/* === Gallery card (Médias pane) — list of media + add form === */
.gallery-card {
    margin-top: 1.5rem;
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}
.gallery-card__header { margin-bottom: 1rem; }
.gallery-card__header h3 {
    margin: 0 0 .25rem;
    color: var(--primary-dark);
    font-size: 1rem;
}
.gallery-card__hint {
    margin: 0;
    font-size: .82rem;
    color: var(--muted);
}
.gallery-empty {
    margin: 0 0 1.25rem;
    padding: 1rem 1.25rem;
    background: var(--surface);
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    color: var(--muted);
    font-size: .9rem;
    text-align: center;
}
.gallery-grid {
    list-style: none; padding: 0; margin: 0 0 1.25rem;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: .85rem;
}
/* ── Gallery item card ── */
.gallery-item {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    overflow: visible;
    display: flex; flex-direction: column;
    position: relative;
    cursor: grab;
}
.gallery-item__thumb-wrap {
    position: relative;
    width: 100%; aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--surface-alt);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.gallery-item__thumb {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
/* Order badge — top-left, purely visual */
.gallery-item__order {
    position: absolute; top: .35rem; left: .35rem;
    background: rgba(27, 58, 42, .82);
    color: var(--bg);
    font-size: .68rem; font-weight: 700;
    padding: .1rem .4rem;
    border-radius: 999px;
    letter-spacing: .03em;
    pointer-events: none;
    z-index: 2;
}
/* Hover action bar — top-right */
.gallery-item__actions {
    position: absolute; top: .35rem; right: .35rem;
    display: flex; flex-direction: row; gap: .2rem;
    opacity: 0;
    transition: opacity .15s;
    z-index: 3;
}
.gallery-item:hover .gallery-item__actions { opacity: 1; }
/* Touch devices have no hover — the action bar would stay invisible, making
   delete/reorder unreachable on a phone. Always show it there, and grow the
   buttons toward a comfortable tap target. */
@media (hover: none) {
    .gallery-item__actions { opacity: 1; }
    .gallery-item__action { width: 36px; height: 36px; }
    .gallery-item__action svg { width: 16px; height: 16px; }
}
.gallery-item__action {
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,.55);
    color: #fff;
    border: none; border-radius: 4px;
    cursor: pointer;
    padding: 0;
    line-height: 1;
    flex-shrink: 0;
    transition: background .12s;
}
.gallery-item__action:hover { background: rgba(0,0,0,.75); }
.gallery-item__action svg { width: 14px; height: 14px; display: block; }
.gallery-item__drag-handle { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.gallery-item__drag-handle:active { cursor: grabbing; }
.gallery-item__drag-handle:active { cursor: grabbing; }
.gallery-item__delete-form { margin: 0; padding: 0; }
.gallery-item__delete-btn { background: rgba(180,30,30,.65); }
.gallery-item__delete-btn:hover { background: rgba(180,30,30,.9); }
/* Drag states */
.gallery-item.is-dragging {
    opacity: .35;
    cursor: grabbing;
}
.gallery-item.is-drop-target {
    outline: 2px dashed var(--accent);
    outline-offset: -4px;
}
/* Card body — compact caption strip */
.gallery-item__body {
    padding: .5rem .65rem;
    flex: 1;
}
.gallery-item__caption {
    margin: 0;
    font-size: .8rem; color: var(--text);
    line-height: 1.35;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
/* Slide-down edit panel */
.gallery-item__edit-panel {
    padding: .75rem;
    border-top: 1px solid var(--border-soft);
    background: var(--surface-alt);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.gallery-item__edit-panel[hidden] { display: none; }
.gallery-item__form {
    display: flex; flex-direction: column; gap: .6rem;
}
.gallery-item__form label {
    display: flex; flex-direction: column; gap: .2rem;
    font-size: .75rem; color: var(--muted);
}
.gallery-item__form input[type=text] {
    padding: .35rem .55rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .85rem;
    background: var(--surface);
}
.gallery-item__form-actions {
    display: flex; gap: .5rem;
    flex-wrap: wrap;
}
.gallery-item__form-actions .btn { padding: .3rem .65rem; font-size: .8rem; }
/* Add-media form */
.gallery-add-form {
    margin-top: 1rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
}
.gallery-add-form h4 {
    margin: 0 0 .85rem;
    color: var(--primary-dark);
    font-size: .92rem;
    font-weight: 600;
}
.gallery-add-form__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .75rem;
    margin-top: .85rem;
}
.gallery-add-form__row label {
    display: flex; flex-direction: column; gap: .25rem;
    font-size: .8rem; color: var(--muted);
}
.gallery-add-form__row input[type=text] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .88rem;
    background: var(--surface);
}
.gallery-add-form__row input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
.gallery-add-form__actions {
    display: flex; justify-content: flex-end;
    margin-top: .85rem;
}
@media (max-width: 640px) {
    .gallery-add-form__row { grid-template-columns: 1fr; }
}

/* === Cover upload card (Médias pane) — same look as EPUB card === */
.cover-upload-card {
    margin-top: 0;
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}
.cover-upload-card h3 {
    margin: 0 0 .85rem;
    color: var(--primary-dark);
    font-size: 1rem;
}
.cover-upload-card__current {
    display: flex; gap: 1rem; align-items: flex-start;
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-soft);
}
.cover-upload-card__thumb {
    width: 100px; aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: var(--radius-sm);
    box-shadow: 0 4px 12px rgba(0,0,0,.15);
    flex-shrink: 0;
}

/* === EPUB upload card (Synopsis pane) === */
.epub-upload-card {
    margin-top: 1.5rem;
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}
.epub-upload-card h3 {
    margin: 0 0 .65rem;
    color: var(--primary-dark);
    font-size: 1rem;
}
.epub-upload-card__status {
    margin: 0 0 .85rem;
    font-size: .85rem;
    color: var(--muted);
}
.epub-upload-card__status code {
    background: var(--surface); border: 1px solid var(--border-soft);
    padding: 1px 6px; border-radius: 4px;
    color: var(--primary-dark);
}
.epub-upload-card__version {
    display: flex; flex-direction: column; gap: .35rem;
    margin-top: .85rem;
    font-size: .82rem; color: var(--muted);
}
.epub-upload-card__version input {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .9rem;
    background: var(--surface);
}
.epub-upload-card__version input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}

/* === Médias placeholder (create page) === */
.medias-placeholder {
    text-align: center;
    padding: 2.5rem 1.5rem;
    background: var(--surface-alt);
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    color: var(--muted);
}
.medias-placeholder svg {
    width: 56px; height: 56px;
    color: var(--accent);
    margin: 0 auto .75rem;
    display: block;
    opacity: .85;
}
.medias-placeholder h3 {
    margin: 0 0 .75rem;
    color: var(--primary-dark);
    font-size: 1.05rem;
}
.medias-placeholder p { margin: 0 0 .5rem; line-height: 1.5; }
.medias-placeholder ul {
    text-align: left;
    max-width: 480px;
    margin: 1rem auto;
    padding-left: 1.25rem;
    line-height: 1.7;
}
.medias-placeholder ul strong { color: var(--text); }

/* === Live book-page preview (Apparence pane) ===
 * Mock book-detail card whose colors and fonts are driven by CSS variables
 * (--bp-*) that the JS sets from the palette pickers and font selects.
 * Defaults match the Livralyo global palette so the preview is meaningful
 * even when no per-book override is set. */
.book-preview {
    margin-top: 1.5rem;
    margin-bottom: 1.75rem;
}
.book-preview + fieldset {
    margin-top: 1.5rem;
}
.book-preview__header {
    display: flex; flex-direction: column; gap: .15rem;
    margin-bottom: .65rem;
}
.book-preview__caption {
    font-size: .78rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .06em; font-weight: 600;
}
.book-preview__hint {
    font-size: .8rem; color: var(--muted); font-style: italic;
}
.book-preview__frame {
    --bp-primary:      #2D5040;
    --bp-primary-dark: #1B3A2A;
    --bp-accent:       #C9A227;
    --bp-background:   #F8F4EC;
    --bp-surface:      #FFFFFF;
    --bp-text:         #1A1F18;
    --bp-muted:        #5C5C5C;
    --bp-border:       #E8DFC9;
    --bp-font-display: 'Cinzel', Georgia, serif;
    --bp-font-body:    'Lora', Georgia, serif;

    padding: 2rem 1.75rem;
    border-radius: var(--radius);
    border: 1px solid var(--bp-border);
    background: var(--bp-background);
    color: var(--bp-text);
    font-family: var(--bp-font-body);
    box-shadow: var(--shadow-sm);
}
.book-preview__hero {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: 1.75rem;
    align-items: start;
}
.book-preview__cover {
    width: 130px; aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: 4px;
    box-shadow: 0 6px 20px rgba(0,0,0,.18);
    background: var(--bp-surface);
}
.book-preview__cover--placeholder {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .65rem;
    color: var(--bp-muted);
    text-align: center;
    background:
        repeating-linear-gradient(45deg, transparent 0, transparent 6px, rgba(0,0,0,.03) 6px, rgba(0,0,0,.03) 12px),
        var(--bp-surface);
    border: 1px dashed var(--bp-border);
    box-shadow: none;
    font-size: .75rem; line-height: 1.3;
}
.book-preview__cover--placeholder svg { width: 32px; height: 32px; opacity: .55; }
.book-preview__info { min-width: 0; }
.book-preview__teaser {
    font-family: var(--bp-font-display);
    font-size: .8rem; font-weight: 700;
    color: var(--bp-accent);
    text-transform: uppercase; letter-spacing: .08em;
    margin: 0 0 .5rem;
}
.book-preview__title {
    font-family: var(--bp-font-display);
    font-size: 1.65rem; font-weight: 700; line-height: 1.1;
    color: var(--bp-primary);
    margin: 0 0 .35rem;
}
.book-preview__subtitle {
    color: var(--bp-muted);
    font-size: .92rem; font-style: italic;
    margin: 0 0 .55rem;
}
.book-preview__author {
    font-size: .85rem;
    color: var(--bp-text);
    margin: 0 0 1rem;
}
.book-preview__synopsis {
    font-size: .9rem; line-height: 1.6;
    margin: 0 0 1.25rem;
    padding-left: 1rem;
    border-left: 2px solid var(--bp-accent);
    color: var(--bp-text);
}
.book-preview__buy {
    background: var(--bp-accent);
    color: var(--bp-primary-dark);
    border: none;
    padding: .65rem 1.5rem;
    border-radius: 999px;
    font-family: var(--bp-font-body);
    font-weight: 700; font-size: .9rem;
    cursor: default;
    transition: opacity var(--transition);
}
.book-preview__buy:hover { opacity: .9; }
@media (max-width: 640px) {
    .book-preview__hero { grid-template-columns: 1fr; gap: 1rem; }
    .book-preview__cover { width: 100px; margin: 0 auto; }
}

/* === Custom font upload form — name input + dropzone + compact submit === */
.font-upload-form {
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border-radius: var(--radius);
    border: 1px solid var(--border-soft);
    margin-top: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.font-upload-form__row { display: flex; flex-wrap: wrap; gap: .75rem; }
.font-upload-form__name { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: .35rem; }
.font-upload-form__name span { font-size: .85rem; color: var(--muted); }
.font-upload-form__name input {
    padding: .55rem .75rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); font: inherit; font-size: .9rem;
}
.font-upload-form__name input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}

/* Drag-and-drop file dropzone — reused for font + EPUB uploads.
   `.font-dropzone` kept as alias for backward compatibility. */
.file-dropzone, .font-dropzone {
    position: relative;
    display: flex; align-items: center; gap: 1rem;
    padding: 1.25rem 1.5rem;
    background: var(--surface);
    border: 2px dashed var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.file-dropzone:hover, .file-dropzone.is-dragging,
.font-dropzone:hover, .font-dropzone.is-dragging {
    border-color: var(--accent); background: rgba(201, 162, 39, .06);
}
.file-dropzone.has-file,
.font-dropzone.has-file {
    border-color: var(--primary); background: rgba(45, 80, 64, .04);
    border-style: solid;
}
.file-dropzone__input,
.font-dropzone__input {
    position: absolute; inset: 0;
    opacity: 0; cursor: pointer;
    width: 100%; height: 100%;
}
form .file-dropzone .file-dropzone__input,
form .font-dropzone .font-dropzone__input {
    width: 100%; padding: 0; border: none; background: transparent;
}
.file-dropzone__icon,
.font-dropzone__icon {
    width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-alt);
    border-radius: 50%;
    color: var(--accent);
    flex-shrink: 0;
}
.file-dropzone.has-file .file-dropzone__icon,
.font-dropzone.has-file .font-dropzone__icon {
    background: rgba(45, 80, 64, .12); color: var(--primary);
}
.file-dropzone__icon svg,
.font-dropzone__icon svg { width: 22px; height: 22px; }
.file-dropzone__text,
.font-dropzone__text { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.file-dropzone__text strong,
.font-dropzone__text strong {
    color: var(--text); font-size: .95rem; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.file-dropzone__text span,
.font-dropzone__text span {
    color: var(--muted); font-size: .8rem;
}

.font-upload-form__actions { display: flex; justify-content: flex-end; }
.font-upload-form__actions .btn { padding: .5rem 1.25rem; }

.font-upload-form__success {
    background: var(--success-soft);
    color: var(--success);
    border: 1px solid #bbf7d0;
    padding: .85rem 1.25rem;
    border-radius: var(--radius-sm);
    font-size: .9rem;
}
.font-upload-form__error {
    background: var(--danger-soft);
    color: var(--danger);
    border: 1px solid #fecaca;
    padding: .85rem 1.25rem;
    border-radius: var(--radius-sm);
    font-size: .9rem;
}

/* === Cover crop tool (admin-cover-crop.js) ===
 * Replaces the cover dropzone after file selection with a draggable +
 * resizable 2:3 frame overlay. The frame, mask, handles and toolbar
 * are all injected by JS; these classes are never used before a file
 * is chosen, so there is no visual impact on the initial page render. */

/* Outer container — hidden by default, shown by JS */
.cover-crop-stage {
    display: flex;
    flex-direction: column;
    gap: .85rem;
}

/* Image wrapper — relative so frame + mask can be positioned inside */
.cover-crop-stage__img-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
    max-width: 100%;
    overflow: hidden;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    background: #000;
    cursor: default;
    user-select: none;
    -webkit-user-select: none;
}

/* The display image — fit to container width */
.cover-crop-stage__img {
    display: block;
    max-width: 100%;
    height: auto;
    pointer-events: none;
}

/* Full-cover semi-transparent mask — a "hole" is cut by clip-path in JS */
.cover-crop-mask {
    position: absolute;
    top: 0; left: 0;
    pointer-events: none;
    background: rgba(0, 0, 0, .52);
    /* clip-path is set dynamically by JS to cut a transparent rectangle
       matching the crop frame — creates the outside-dimming effect */
}

/* Draggable crop frame */
.cover-crop-frame {
    position: absolute;
    box-sizing: border-box;
    border: 2px solid rgba(255, 255, 255, .9);
    border-radius: 2px;
    cursor: move;
    touch-action: none;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Rule-of-thirds guide lines */
    background-image:
        linear-gradient(rgba(255,255,255,.18) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.18) 1px, transparent 1px);
    background-size: 33.33% 33.33%;
}

/* Centered "Recadrer" caption inside the frame */
.cover-crop-frame__label {
    color: rgba(255, 255, 255, .85);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-shadow: 0 1px 3px rgba(0,0,0,.7);
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
}

/* Corner resize handles — 10 × 10 px white squares */
.cover-crop-handle {
    position: absolute;
    width: 12px;
    height: 12px;
    background: #fff;
    border: 2px solid rgba(45, 80, 64, .7);
    border-radius: 2px;
    touch-action: none;
}
.cover-crop-handle--nw { top: -6px;  left: -6px;  cursor: nw-resize; }
.cover-crop-handle--ne { top: -6px;  right: -6px; cursor: ne-resize; }
.cover-crop-handle--sw { bottom: -6px; left: -6px;  cursor: sw-resize; }
.cover-crop-handle--se { bottom: -6px; right: -6px; cursor: se-resize; }

/* Toolbar below the image */
.cover-crop-toolbar {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
}

.cover-crop-toolbar__hint {
    flex: 1;
    font-size: .78rem;
    color: var(--muted);
    font-style: italic;
    min-width: 0;
}

.cover-crop-toolbar__reset,
.cover-crop-toolbar__change {
    font-size: .82rem;
    padding: .35rem .85rem;
    white-space: nowrap;
    flex-shrink: 0;
}

.cover-crop-toolbar__change {
    background: transparent;
    border-color: var(--border);
    color: var(--muted);
}
.cover-crop-toolbar__change:hover {
    border-color: var(--primary);
    color: var(--primary);
    background: transparent;
}

/* === Form draft banner (asks user to restore or discard) === */
.form-draft-banner {
    background: #fff7e0;
    border: 1px solid #d4a017;
    border-left: 4px solid #b88600;
    color: #8a5a00;
    padding: .65rem 1rem;
    border-radius: 6px;
    margin: 0 0 1rem;
    display: flex;
    flex-wrap: wrap;
    gap: .55rem;
    align-items: center;
    font-size: .92rem;
}
.form-draft-banner .muted { color: var(--muted); }

/* === Form success banner (top-of-form flash) === */
.form-success-banner {
    background: #ecf7ee;
    border: 1px solid #b7dec0;
    border-left: 4px solid #2d7a3a;
    color: #1f5532;
    padding: .65rem 1rem;
    border-radius: 6px;
    margin-bottom: 1rem;
    font-size: .92rem;
    font-weight: 500;
    animation: form-success-fade 6s forwards;
}
@keyframes form-success-fade {
    0%, 80%   { opacity: 1; max-height: 4rem; }
    100%      { opacity: 0; max-height: 0; padding: 0; margin: 0; border-width: 0; }
}

/* === Form error banner (top-of-form flash) === */
.form-error-banner {
    background: #fdecea;
    border: 1px solid #f5c2c2;
    border-left: 4px solid #c0392b;
    color: #7a1f1f;
    padding: .75rem 1rem;
    border-radius: 6px;
    margin-bottom: 1rem;
    font-size: .92rem;
    line-height: 1.45;
}
.form-error-banner em { font-style: normal; font-weight: 600; }

/* === Inline field hints === */
.field-hint {
    margin: -.4rem 0 .35rem;
    font-size: .82rem;
    color: var(--muted);
}
.field-hint--warning {
    color: #8a5a00;
    background: #fff7e0;
    border-left: 3px solid #d4a017;
    padding: .35rem .55rem;
    border-radius: 4px;
}

/* === Field-label row with inline info icon === */
.field-label-row {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}
.info-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    border-radius: 50%;
    cursor: pointer;
    transition: color .12s ease, background-color .12s ease;
}
.info-icon-btn:hover,
.info-icon-btn[aria-expanded="true"] {
    color: var(--primary);
    background: var(--surface-alt);
}
.info-icon-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* === Status info popover === */
.status-info-popover {
    position: relative;
    margin: .35rem 0 1rem;
    padding: 1rem 1rem .75rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 4px solid var(--accent);
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .06);
    max-width: 640px;
}
.status-info-popover[hidden] { display: none; }
.status-info-popover h4 {
    margin: 0 0 .55rem;
    font-size: .95rem;
    color: var(--primary);
}
.status-info-popover dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .45rem .85rem;
    margin: 0;
}
.status-info-popover dt { margin: 0; }
.status-info-popover dd {
    margin: 0;
    font-size: .88rem;
    line-height: 1.45;
    color: var(--text);
}
.status-info-popover__close {
    position: absolute;
    top: .25rem;
    right: .35rem;
    width: 1.6rem;
    height: 1.6rem;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    border-radius: 50%;
}
.status-info-popover__close:hover {
    color: var(--text);
    background: var(--surface-alt);
}

/* === Page builder ("Mise en page" tab) =================================== */
.page-builder {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, .9fr);
    gap: 1.5rem;
    margin-top: 1rem;
    align-items: start;
}
@media (max-width: 960px) {
    .page-builder { grid-template-columns: 1fr; }
}

.section-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.section-list__add {
    margin-top: .85rem;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

.section-item {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    gap: .75rem;
    align-items: center;
    padding: .65rem .8rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    transition: background-color .12s ease, border-color .12s ease, opacity .12s ease;
}
.section-item.is-dragging   { opacity: .4; }
.section-item.is-drop-target { box-shadow: 0 0 0 2px var(--accent) inset; }

.section-item--hidden { opacity: .5; background: var(--surface-alt); }
.section-item--hidden .section-item__title { text-decoration: line-through dotted; }

.section-item--empty { border-color: #d4a017; background: #fff8e6; }
.section-item--empty .section-item__title { color: var(--muted); }

.section-item--custom {
    border-left: 4px solid var(--accent);
}

/* Locked en-tête card — sits above the section list, cannot be dragged or hidden.
 * Visually distinct from regular section items so the author understands at a
 * glance that hero/cover/title/price are NOT part of the layout-driven list. */
.section-item--locked {
    background: linear-gradient(180deg, rgba(45, 80, 64, .04), rgba(45, 80, 64, 0)),
                var(--surface);
    border: 1px solid var(--primary);
    border-left-width: 4px;
    border-radius: 8px;
    margin-bottom: .85rem;
    padding: .65rem .8rem;
    display: grid;
    /* Same column shape as regular section rows so the actions column (palette
     * pastille) lines up on the right instead of wrapping to a new row. */
    grid-template-columns: auto auto 1fr auto;
    gap: .75rem;
    align-items: center;
    cursor: not-allowed;
}
/* Lock the cursor only on the non-interactive parts of the locked row;
 * the palette pastille and its panel must stay clickable. */
.section-item--locked .section-item__actions,
.section-item--locked .section-item__actions *,
.section-item--locked .section-item__palette,
.section-item--locked .section-item__palette * { cursor: auto; }
.section-item--locked .section-item__actions button { cursor: pointer; }
.section-item__handle--locked { color: var(--primary); }
.section-item--locked .section-item__icon { color: var(--primary); }
.section-item--locked .section-item__title { color: var(--primary); }
.section-item--locked .section-item__hint { color: var(--muted); font-style: italic; }

.section-item__handle {
    cursor: grab;
    color: var(--muted);
    display: inline-flex; align-items: center;
    /* Suppress native browser scroll when the user starts a drag from the
     * handle on touch devices (Pointer Events drag implementation). */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}
.section-item__handle:active { cursor: grabbing; }
.section-item__handle svg { width: 18px; height: 18px; pointer-events: none; }

.section-item__icon {
    color: var(--primary);
    display: inline-flex; align-items: center;
}
.section-item__icon svg { width: 20px; height: 20px; }

.section-item__main { min-width: 0; }
.section-item__title {
    font-weight: 600;
    color: var(--text);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.section-item__hint {
    font-size: .8rem;
    color: var(--muted);
    margin-top: .15rem;
}
.section-item__empty-tag {
    color: #8a5a00;
    font-weight: 500;
}

.section-item__actions {
    display: inline-flex;
    gap: .25rem;
}
.section-item__btn {
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--muted);
    cursor: pointer;
    padding: 0;
    transition: color .12s ease, background-color .12s ease, border-color .12s ease;
}
.section-item__btn:hover {
    color: var(--primary);
    border-color: var(--border);
    background: var(--surface-alt);
}
.section-item__btn[aria-pressed="false"] { color: #b94a48; }
.section-item__btn.is-active { color: var(--primary); border-color: var(--primary); }
.section-item__btn--danger:hover { color: #b94a48; border-color: #f5c2c2; background: #fdecea; }
.section-item__btn svg { width: 16px; height: 16px; }

/* Per-section palette panel — dropped below the section row when toggled.
 * The page-builder list lives OUTSIDE the main #book-form, so the
 * `form .palette-row input[type=color]` rules above do not apply here.
 * We re-declare swatch sizing locally so the picker renders as a 36px
 * circle instead of the browser's default oversized rectangle. */
.section-item__palette {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .65rem .75rem;
    margin-top: .35rem;
    border: 1px dashed var(--border);
    border-radius: 8px;
    background: var(--surface-alt, var(--surface));
}
.section-item__palette[hidden] { display: none; }
.section-item__palette .palette-row { padding: .35rem .5rem; }
.section-item__palette input[type=color].palette-row__swatch {
    width: 36px; height: 36px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: var(--surface-alt);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
}

/* === Page-builder preview pane (real iframe of the public page) ======== */
.page-builder__preview-col {
    position: sticky;
    top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}
.page-builder__preview-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .5rem;
}
.page-builder__preview-title {
    margin: 0;
    font-size: .9rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--muted);
}
.page-builder__preview-open {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .82rem;
    color: var(--primary);
    text-decoration: none;
    padding: .2rem .5rem;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: var(--surface);
}
.page-builder__preview-open:hover {
    background: var(--surface-alt);
    border-color: var(--primary);
}
.page-builder__preview-frame-wrap {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
    height: calc(100vh - 9rem);
    min-height: 480px;
}
.page-builder__preview-iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: #fff;
}
.page-builder__preview-loader {
    position: absolute;
    top: .65rem; left: .65rem;
    background: rgba(255, 255, 255, .92);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: .35rem .65rem;
    font-size: .82rem;
    color: var(--muted);
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    box-shadow: 0 4px 10px rgba(0, 0, 0, .08);
}
.page-builder__preview-loader[hidden] { display: none; }
.page-builder__preview-loader .spinner {
    width: 12px; height: 12px;
    border: 2px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: pb-spin .7s linear infinite;
}
@keyframes pb-spin { to { transform: rotate(360deg); } }

/* === Reviews bulk action bar =========================================== */
.reviews-bulk-bar {
    position: sticky;
    top: 0;
    z-index: 5;
    display: flex;
    gap: .65rem;
    align-items: center;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: .5rem .85rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-sm);
}
.reviews-bulk-bar__spacer { flex: 1; }
.reviews-row__check {
    width: 18px; height: 18px; cursor: pointer;
}

/* === Page-builder fullscreen preview modal ============================== */
/* The modal is JS-portalled to <body> at open time, so its stacking context
 * is the document root — guaranteed above the admin sticky header (z-index:10)
 * and the saved-button bar (z-index:5). z-index 9999 keeps headroom. */
.page-builder-fullscreen {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .82);
    z-index: 9999;
    display: flex;
    flex-direction: column;
    padding: 3.5rem 2rem 2rem;  /* top extra space so close button is reachable */
}
.page-builder-fullscreen[hidden] { display: none; }
.page-builder-fullscreen__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: #fff;
    margin-bottom: .65rem;
}
.page-builder-fullscreen__header h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 500;
    color: #fff;
}
.page-builder-fullscreen__close {
    /* Absolute position at top-right of the viewport so the X is ALWAYS
     * reachable, even if the header itself were ever clipped. */
    position: absolute;
    top: 1rem;
    right: 1rem;
    width: 2.4rem; height: 2.4rem;
    border: 1px solid rgba(255, 255, 255, .3);
    background: rgba(255, 255, 255, .08);
    color: #fff;
    font-size: 1.5rem;
    line-height: 1;
    border-radius: 50%;
    cursor: pointer;
    z-index: 1;
}
.page-builder-fullscreen__close:hover {
    background: rgba(255, 255, 255, .18);
}
.page-builder-fullscreen__body {
    flex: 1;
    background: #fff;
    border-radius: 8px;
    overflow: hidden;
    min-height: 0;
}
.page-builder-fullscreen__iframe {
    width: 100%; height: 100%;
    border: 0;
    display: block;
    background: #fff;
}

/* Section CRUD success toast */
.page-builder-toast {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 1100;
    background: #1f5532;
    color: #fff;
    padding: .55rem .9rem;
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
    font-size: .9rem;
    opacity: 0;
    transform: translateY(.5rem);
    transition: opacity .25s ease, transform .25s ease;
    pointer-events: none;
}
.page-builder-toast.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* === Custom-section editor modal ========================================= */
.section-modal {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 1rem;
}
.section-modal[hidden] { display: none; }
.section-modal__panel {
    background: var(--surface);
    border-radius: 12px;
    width: min(720px, 100%);
    max-height: calc(100vh - 2rem);
    overflow: auto;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
    padding: 1.25rem 1.5rem 1.5rem;
}
.section-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .75rem;
    border-bottom: 1px solid var(--border);
    padding-bottom: .55rem;
}
.section-modal__header h3 { margin: 0; font-size: 1.1rem; color: var(--primary); }
.section-modal__close {
    width: 2rem; height: 2rem;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: 1.5rem;
    line-height: 1;
    border-radius: 50%;
    cursor: pointer;
}
.section-modal__close:hover { background: var(--surface-alt); color: var(--text); }
.section-modal label { display: block; margin: .65rem 0; font-weight: 500; }
.section-modal label input,
.section-modal label textarea {
    width: 100%;
    margin-top: .3rem;
    font-family: inherit;
}
.section-modal label textarea {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .9rem;
    resize: vertical;
}
.section-modal__media-fieldset {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .65rem .85rem;
    margin: .85rem 0;
}
.section-modal__media-fieldset legend {
    padding: 0 .35rem;
    color: var(--primary);
    font-weight: 600;
}
.section-modal__media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: .5rem;
}
.section-modal__media-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .35rem;
    background: var(--surface-alt);
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
}
.section-modal__media-card.is-selected { border-color: var(--accent); background: var(--surface); }
.section-modal__media-card input[type="checkbox"] {
    position: absolute; top: .35rem; left: .35rem;
    width: 18px; height: 18px;
}
.section-modal__media-card img {
    width: 100%; height: 90px; object-fit: cover; border-radius: 4px;
}
.section-modal__media-card select { font-size: .8rem; }
.section-modal__actions {
    display: flex;
    justify-content: flex-end;
    gap: .5rem;
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--border);
}

/* === Sales list — clickable rows + slide-in detail panel ============= */
.sale-row { cursor: pointer; transition: background-color .12s ease; }
.sale-row:hover { background: var(--surface-alt, rgba(0, 0, 0, .03)); }
.sale-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* Wrapper covers the viewport so the backdrop + inner panel sit above the
 * page chrome. `hidden` hides it entirely until JS opens it. */
.sale-panel {
    position: fixed;
    inset: 0;
    z-index: 60;
    pointer-events: none;
}
.sale-panel:not([hidden]) { pointer-events: auto; }
.sale-panel__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(27, 58, 42, .35);
    opacity: 0;
    transition: opacity .22s ease;
    backdrop-filter: blur(2px);
}
.sale-panel.is-open .sale-panel__backdrop { opacity: 1; }
.sale-panel__inner {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: clamp(420px, 50vw, 720px);
    background: var(--surface);
    box-shadow: -16px 0 40px rgba(0, 0, 0, .18);
    transform: translateX(100%);
    transition: transform .25s cubic-bezier(.2, .7, .2, 1);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.sale-panel.is-open .sale-panel__inner { transform: translateX(0); }
.sale-panel__close {
    position: absolute;
    top: .85rem; right: .85rem;
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-alt, rgba(0, 0, 0, .04));
    border: 1px solid transparent;
    border-radius: 50%;
    font-size: 1.4rem; line-height: 1;
    color: var(--muted);
    cursor: pointer;
    z-index: 2;
    transition: color .12s ease, background-color .12s ease, border-color .12s ease;
}
.sale-panel__close:hover {
    color: var(--text);
    background: var(--surface);
    border-color: var(--border);
}
.sale-panel__body {
    flex: 1;
    overflow-y: auto;
    padding: 2rem 1.75rem 2rem;
}
/* The injected detail keeps its native h1/section styling but loses any
 * top margin so it sits right under the close button. The global
 * `h1::after` gold underline is decorative on full-page views; in the
 * panel it competes with the header chrome (close button + state badge),
 * so we hide it. */
.sale-panel__body [data-sale-detail] > h1:first-child,
.sale-panel__body [data-promo-detail] .promo-detail__head h1,
.sale-panel__body [data-book-detail] .book-detail__head h1 {
    margin-top: 0;
    padding-right: 3rem;
}
.sale-panel__body [data-sale-detail] h1::after,
.sale-panel__body [data-promo-detail] h1::after,
.sale-panel__body [data-book-detail] h1::after { display: none; }

.sale-panel__loader {
    display: flex; align-items: center; justify-content: center;
    padding: 3rem 0;
}
.sale-panel__loader .spinner {
    width: 24px; height: 24px;
    border: 3px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: pb-spin .7s linear infinite;
}

/* Lock body scroll when the panel is open so the page underneath doesn't
 * scroll behind the backdrop. */
body.has-sale-panel { overflow: hidden; }

@media (max-width: 720px) {
    .sale-panel__inner {
        width: 100%;
        box-shadow: none;
    }
    .sale-panel__body { padding: 1.25rem 1rem; }
}
@media (prefers-reduced-motion: reduce) {
    .sale-panel__inner { transition: none; }
    .sale-panel__backdrop { transition: none; }
}

/* === Sales detail — action cards (regen link / refund) ============== */
/* Used both inline on the full /admin/ventes/{id} page and inside the
 * slide-in panel from the list. Scope is on .sale-action so the styling
 * stays consistent in both contexts. */
.sale-action {
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 1.25rem 1.4rem;
    margin-bottom: 1rem;
    background: var(--surface);
    box-shadow: none;
}
.sale-action__head {
    display: flex;
    gap: .85rem;
    align-items: flex-start;
    margin-bottom: 1rem;
}
.sale-action__head svg {
    width: 22px; height: 22px;
    color: var(--primary);
    flex-shrink: 0;
    margin-top: .15rem;
}
.sale-action__head h2 {
    font-family: var(--font-body, system-ui), sans-serif;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
    margin: 0 0 .25rem;
    text-transform: none;
    letter-spacing: 0;
}
.sale-action__head p {
    margin: 0;
    color: var(--muted);
    font-size: .88rem;
    line-height: 1.45;
}
.sale-action__cta {
    height: 40px;
    padding: 0 1.1rem;
    font-size: .9rem;
    font-weight: 600;
    box-sizing: border-box;
}
/* Regen card: indent the standalone CTA so it lines up under the title
 * rather than under the icon. Indent = icon width (22px) + flex gap (.85rem). */
.sale-action--regen .sale-action__cta {
    margin-left: calc(22px + .85rem);
}

/* Refund card uses a 2-row grid: the label spans the input column on row 1,
 * and the input + the button share row 2. Putting them in the same row
 * (rather than aligning a single-line button to a 2-line label/input block)
 * gives a clean side-by-side alignment of the same-height controls. */
.sale-action__row {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
        "label   ."
        "input   button";
    gap: .35rem .75rem;
    margin-left: calc(22px + .85rem);
}
.sale-action__totp { display: contents; }
.sale-action__totp > span {
    grid-area: label;
    font-size: .7rem;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .12em;
}
.sale-action__totp > input {
    grid-area: input;
    height: 40px;
    box-sizing: border-box;
    padding: 0 .85rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font: inherit;
    font-feature-settings: "tnum";
    letter-spacing: .25em;
    background: var(--surface);
    color: var(--text);
    min-width: 0;
}
.sale-action__row > .btn { grid-area: button; align-self: stretch; }
.sale-action__totp > input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(45, 80, 64, .12);
}

/* Danger variant — red accent on the icon + cta, soft red background. */
.sale-action--danger {
    border-color: #f5c2c2;
    background: linear-gradient(180deg, #fff8f8, var(--surface));
}
.sale-action--danger .sale-action__head svg { color: #b94a48; }
.sale-action--danger .btn-danger {
    background: #b94a48;
    border-color: #b94a48;
    color: #fff;
}
.sale-action--danger .btn-danger:hover { background: #a13d3b; border-color: #a13d3b; }

/* Inside the panel: tighten spacing and drop the panel's own padding clash. */
.sale-panel__body .sale-action { margin-bottom: .85rem; }
.sale-panel__body .sale-action:last-child { margin-bottom: 0; }

/* === Promos list — badges, chips, toggle button ===================== */
.promo-row { cursor: pointer; transition: background-color .12s ease; }
.promo-row:hover { background: var(--surface-alt, rgba(0, 0, 0, .03)); }
.promo-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.ambassador-code-pill {
    display: inline-block;
    padding: .2rem .55rem;
    border-radius: 6px;
    background: rgba(45, 80, 64, .08);
    color: var(--primary-dark);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
    font-size: .85rem;
    font-weight: 600;
    letter-spacing: .04em;
}

.discount-badge {
    display: inline-block;
    padding: .2rem .55rem;
    border-radius: 999px;
    background: rgba(201, 162, 39, .15);
    color: #8a6a14;
    font-weight: 700;
    font-size: .82rem;
    font-feature-settings: "tnum";
}

.scope-chip, .target-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .2rem .55rem;
    border-radius: 999px;
    background: var(--surface-alt, rgba(0, 0, 0, .04));
    color: var(--muted);
    font-size: .78rem;
    font-weight: 500;
}
.scope-chip svg, .target-chip svg { width: 13px; height: 13px; flex-shrink: 0; }
.scope-chip--books { background: rgba(45, 80, 64, .08); color: var(--primary-dark); }
.target-chip--targeted { background: rgba(201, 162, 39, .14); color: #8a6a14; }

.promo-period { font-size: .85rem; color: var(--muted); }
.promo-period small { font-feature-settings: "tnum"; }

.usage-meter { display: flex; flex-direction: column; gap: .15rem; min-width: 80px; }
.usage-meter__count { font-size: .85rem; font-weight: 600; font-feature-settings: "tnum"; color: var(--text); }
.usage-meter__bar {
    display: block;
    height: 4px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .08);
    overflow: hidden;
}
.usage-meter__bar > span {
    display: block;
    height: 100%;
    background: var(--primary);
    transition: width .25s ease;
}
.usage-meter--warn .usage-meter__bar > span { background: #b94a48; }
.usage-meter--warn .usage-meter__count { color: #b94a48; }
.usage-meter--unlimited { display: inline-flex; align-items: baseline; gap: .35rem; }
.usage-meter--unlimited small { color: var(--muted); font-size: .75rem; }

.promo-state-cell {
    display: inline-grid;
    grid-template-columns: 100px auto;
    align-items: center;
    gap: .55rem;
}

.code-state-badge {
    display: inline-block;
    padding: .22rem .65rem;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    line-height: 1.4;
    white-space: nowrap;
    /* Centred inside the fixed-width grid cell so the ON/OFF toggle column
     * to the right lines up across rows regardless of label length. */
    text-align: center;
    justify-self: stretch;
    box-sizing: border-box;
}
.code-state-badge--active    { background: rgba(45, 110, 70, .15);  color: #1f6e3f; }
.code-state-badge--inactive  { background: rgba(0, 0, 0, .06);      color: var(--muted); }
.code-state-badge--expired   { background: rgba(185, 74, 72, .14);  color: #b94a48; }
.code-state-badge--scheduled { background: rgba(201, 162, 39, .18); color: #8a6a14; }
.code-state-badge--archived  { background: rgba(0, 0, 0, .12);      color: #555; }
/* Archived rows are dimmed but kept clickable so the admin can review the
 * historical detail. The discount/scope chips inside reuse their normal
 * colours so the row still reads cleanly. */
.promo-row--archived { opacity: .55; }
.promo-row--archived:hover { opacity: .75; }

.promo-toggle-btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: 0 .25rem;
    background: transparent;
    border: 0;
    cursor: pointer;
    font: inherit;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .08em;
    color: var(--muted);
    text-transform: uppercase;
}
.promo-toggle-btn__track {
    position: relative;
    width: 32px; height: 18px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .15);
    transition: background .15s ease;
}
.promo-toggle-btn__thumb {
    position: absolute;
    top: 2px; left: 2px;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--surface);
    transition: transform .15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
}
.promo-toggle-btn[aria-pressed="true"] .promo-toggle-btn__track { background: var(--primary); }
.promo-toggle-btn[aria-pressed="true"] .promo-toggle-btn__thumb { transform: translateX(14px); }
.promo-toggle-btn[aria-pressed="true"] { color: var(--primary); }
.promo-toggle-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }
.promo-toggle-btn:disabled { opacity: .5; cursor: progress; }

/* === Promo detail panel chrome ===================================== */
.promo-detail__head {
    display: flex; align-items: center; gap: .8rem;
    padding-right: 3rem;
    /* Breathing room before the first card so the title bar reads as a
     * standalone header rather than touching the table top. */
    margin-bottom: 1.25rem;
}
.promo-detail__head-meta {
    display: flex; align-items: center; gap: .65rem;
    flex-shrink: 0;
}
.promo-detail__head h1 {
    font-size: 1.25rem;
    margin: 0;
    flex: 1;
    display: flex; align-items: center; gap: .65rem; flex-wrap: wrap;
}
.promo-detail__code {
    font-family: var(--font-mono, ui-monospace, monospace);
    background: rgba(45, 80, 64, .1);
    color: var(--primary-dark);
    padding: .2rem .65rem;
    border-radius: 6px;
    font-size: 1rem;
}
.promo-detail__discount {
    background: rgba(201, 162, 39, .18);
    color: #8a6a14;
    padding: .2rem .65rem;
    border-radius: 999px;
    font-weight: 700;
    font-size: .9rem;
}
.promo-detail__book-list {
    margin: .4rem 0 0;
    padding: 0 0 0 1.1rem;
    color: var(--muted);
    font-size: .9rem;
}
.promo-detail__email-chip {
    display: inline-block;
    padding: .15rem .45rem;
    border-radius: 4px;
    background: rgba(0, 0, 0, .05);
    color: var(--muted);
    font-size: .8rem;
    margin: .1rem .25rem .1rem 0;
}
.promo-detail__bar {
    margin-top: .35rem;
    height: 6px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .08);
    overflow: hidden;
}
.promo-detail__bar-fill {
    height: 100%;
    background: var(--primary);
    transition: width .25s ease;
}
/* Detail-table card: no h2 (the panel header already provides context),
 * but keep balanced vertical padding so the first row doesn't sit flush
 * against the rounded top corner — that visual collision was reading as
 * "the row is overflowing the card". */
.section--detail-table { padding: .85rem 1.25rem; }
.section--detail-table .admin-detail-table { margin: 0; }
.admin-detail-table {
    width: 100%;
    border-collapse: collapse;
}
.admin-detail-table th {
    text-align: left;
    padding: .85rem 1rem .85rem 0;
    font-weight: 500;
    color: var(--muted);
    width: 38%;
    vertical-align: top;
    font-size: .85rem;
}
.admin-detail-table td {
    padding: .85rem 0;
    font-size: .92rem;
    vertical-align: top;
}
.admin-detail-table tr + tr th,
.admin-detail-table tr + tr td { border-top: 1px solid var(--border); }

/* The promo panel reuses the .sale-panel chrome — alias data-promo-panel
 * to the same visual styling without copying the rules. Already handled
 * because the markup uses .sale-panel class + a different data-* hook. */

/* Sales attributable to a promo, rendered inside the promo detail panel.
 * Compact rows, smaller font, no shadow — it's a sub-table inside an
 * already framed card. */
.promo-sales-table {
    margin: 1rem 0 0;
    box-shadow: none;
    font-size: .88rem;
}
.promo-sales-table th,
.promo-sales-table td { padding: .55rem .65rem; }
.promo-sales-table tbody tr + tr td { border-top: 1px solid var(--border-soft); }
.promo-sales-table small { font-size: .82rem; color: var(--muted); }

/* === Favicon upload widget (settings → identité) ====================
 * Two-thumbnail board: current favicon on the left, click-to-pick (or
 * post-crop preview) on the right. The actual <input type="file"> is
 * visually hidden — the dropzone label triggers it. The cropped image
 * is staged client-side and only persists when the main settings form
 * is submitted (the file ships as part of #settings-form). */
.favicon-upload {
    position: relative; /* contient l'input fichier sr-only (sinon il étend le scroll horizontal) */
    margin-top: 1rem;
    padding: 1.25rem 1.4rem 1.1rem;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    background: var(--surface-alt);
}
.favicon-upload__label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .14em;
    margin-bottom: 1rem;
}
.favicon-upload__flash { margin: 0 0 .85rem; }

.favicon-upload__board {
    display: flex; align-items: center; gap: 1.1rem;
    flex-wrap: wrap;
}
.favicon-upload__slot {
    display: flex; flex-direction: column; align-items: center; gap: .45rem;
    margin: 0;
}
.favicon-upload__slot figcaption {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--muted);
    font-weight: 600;
}
.favicon-upload__arrow {
    font-size: 1.4rem;
    color: var(--muted);
    line-height: 1;
    margin-bottom: 1.1rem; /* aligns with the thumb, ignoring caption row */
}
.favicon-upload__thumb {
    width: 72px; height: 72px;
    border-radius: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.favicon-upload__thumb img {
    max-width: 100%; max-height: 100%;
    width: 44px; height: 44px;
    object-fit: contain;
}
/* "Nouveau" thumb starts as a clickable dropzone with an upload icon.
 * Once a cropped preview is dropped in, .has-file removes the dashed
 * affordance and shows the cropped image like the "Actuel" slot. */
.favicon-upload__dropzone {
    display: flex; flex-direction: column; align-items: center; gap: .45rem;
    cursor: pointer;
    /* So the input which sits next to the dropzone in markup doesn't break
     * the column flow when keyboard-focused. */
}
.favicon-upload__thumb--new {
    border-style: dashed;
    border-color: var(--border);
    color: var(--muted);
    transition: border-color .15s, color .15s, background .15s;
}
.favicon-upload__thumb--new svg { width: 26px; height: 26px; }
.favicon-upload__dropzone:hover .favicon-upload__thumb--new,
.favicon-upload__dropzone:focus-within .favicon-upload__thumb--new {
    border-color: var(--primary);
    color: var(--primary);
    background: var(--surface);
}
.favicon-upload__thumb--new.has-file {
    border-style: solid;
    border-color: var(--accent);
    background: var(--surface);
}
.favicon-upload__thumb--new.has-file svg { display: none; }
.favicon-upload__dropzone-label {
    font-size: .85rem;
    color: var(--text);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-color: var(--border);
}
.favicon-upload__dropzone:hover .favicon-upload__dropzone-label {
    text-decoration-color: var(--primary);
    color: var(--primary);
}
.favicon-upload__input {
    /* Visually hidden but still focusable + ships as part of the form.
     * `display:none` would also work but that drops it from tab order. */
    position: absolute;
    left: 0; top: 0; /* pin to the (now relative) parent so it can't extend page scroll */
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.favicon-upload__hint {
    display: flex; align-items: flex-start; gap: .55rem;
    margin: 1rem 0 0;
    padding: .7rem .9rem;
    background: color-mix(in srgb, var(--accent) 14%, var(--surface) 86%);
    border-left: 3px solid var(--accent);
    border-radius: 6px;
    font-size: .88rem;
    color: var(--text);
}
.favicon-upload__hint svg {
    width: 16px; height: 16px;
    flex-shrink: 0;
    margin-top: 2px;
    color: var(--accent);
}
.favicon-upload__hint strong { color: var(--primary); }

.favicon-upload__formats {
    display: block;
    color: var(--muted);
    font-size: .8rem;
    margin-top: .85rem;
}

/* === Favicon crop modal (admin-favicon-crop.js) ====================== */
.favicon-crop-modal {
    border: 0;
    padding: 0;
    border-radius: 14px;
    width: min(560px, calc(100vw - 2rem));
    max-width: none;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 24px 60px rgba(27, 58, 42, .35), 0 4px 12px rgba(0, 0, 0, .08);
    margin: auto;
}
.favicon-crop-modal::backdrop { background: rgba(27, 58, 42, .55); backdrop-filter: blur(2px); }
.favicon-crop-modal__inner { display: flex; flex-direction: column; }
.favicon-crop-modal__header {
    display: flex; align-items: center; justify-content: space-between;
    padding: .9rem 1.25rem;
    background: var(--primary);
    color: var(--surface);
}
.favicon-crop-modal__header h2 {
    font-size: 1.05rem; margin: 0; color: inherit;
    font-weight: 600; text-transform: none; letter-spacing: 0;
}
.favicon-crop-modal__close {
    background: none; border: 0; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: inherit;
    padding: 0 .25rem; opacity: .85;
}
.favicon-crop-modal__close:hover { opacity: 1; }
.favicon-crop-modal__stage {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    background: repeating-conic-gradient(rgba(0,0,0,.04) 0% 25%, transparent 0% 50%) 50% / 16px 16px;
    overflow: hidden;
    user-select: none;
    touch-action: none;
}
.favicon-crop-modal__stage img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: contain;
    pointer-events: none;
    -webkit-user-drag: none;
}
.favicon-crop-modal__frame {
    position: absolute;
    box-sizing: border-box;
    border: 2px solid var(--accent);
    box-shadow: 0 0 0 9999px rgba(27, 58, 42, .55);
    cursor: move;
    touch-action: none;
}
.favicon-crop-modal__handle {
    position: absolute;
    right: -7px; bottom: -7px;
    width: 14px; height: 14px;
    background: var(--accent);
    border: 2px solid var(--surface);
    border-radius: 50%;
    cursor: nwse-resize;
}
.favicon-crop-modal__footer {
    display: flex; justify-content: flex-end; gap: .6rem;
    padding: .85rem 1.25rem;
    background: var(--surface-alt, #f7f4ec);
    border-top: 1px solid var(--border);
}

/* === Book detail panel (admin/livres/{id} → slide-in) =================
 * Layout for the standalone book-detail.php view (and its panel-injected
 * counterpart). Shares chrome with sales/promo panels (.sale-panel),
 * adds book-specific cover + stats UI. */
.book-detail__head {
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 1.25rem;
    align-items: start;
    margin-bottom: 1.75rem;
}
.book-detail__cover {
    width: 96px; aspect-ratio: 2 / 3;
    border-radius: 8px;
    overflow: hidden;
    background: var(--surface-alt);
    border: 1px solid var(--border);
}
.book-detail__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.book-detail__cover-placeholder {
    width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
    color: var(--muted);
}
.book-detail__cover-placeholder svg { width: 32px; height: 32px; }
.book-detail__head-body { min-width: 0; }
.book-detail__head-body h1 { margin: .35rem 0 .25rem; font-size: 1.6rem; }
.book-detail__subtitle {
    margin: 0 0 .85rem;
    color: var(--muted);
    font-size: .95rem;
    font-style: italic;
}
.book-detail__head-actions {
    display: flex; gap: .5rem; flex-wrap: wrap;
    margin-top: .85rem;
}
.book-detail__head-actions .btn {
    display: inline-flex; align-items: center; gap: .4rem;
}
.book-detail__head-actions .btn svg { width: 14px; height: 14px; }

.book-detail__synopsis {
    margin: 0;
    color: var(--text);
    line-height: 1.55;
    white-space: pre-wrap;
}

.book-detail__sales-summary {
    display: flex; gap: 1.25rem; flex-wrap: wrap;
    margin-bottom: 1rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border-radius: 8px;
    border: 1px solid var(--border-soft);
}
.book-detail__stat {
    display: flex; flex-direction: column; gap: .15rem;
    min-width: 0;
}
.book-detail__stat-value {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--primary);
    line-height: 1.2;
}
.book-detail__stat-label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--muted);
    font-weight: 600;
}

.book-sale-row { cursor: pointer; transition: background-color .12s ease; }
.book-sale-row:hover { background: var(--surface-alt, rgba(0,0,0,.03)); }
.book-sale-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* === Book detail — sales table fitted to the slide-in panel ============
 * The default .admin-table styles let columns size to content, which makes
 * the table overflow inside the panel (~520px wide). Lock columns with
 * table-layout:fixed and truncate the email cell so the panel never needs
 * a horizontal scrollbar. */
.book-detail__sales-table {
    table-layout: fixed;
    width: 100%;
}
.book-detail__col-date   { width: 7.5rem; }
.book-detail__col-amount { width: 5rem;   text-align: right; }
.book-detail__col-status { width: 6.5rem; }
.book-detail__sales-table th,
.book-detail__sales-table td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.book-detail__cell-email {
    direction: ltr;
}
.book-detail__sales-table .status-badge { font-size: .72rem; padding: .2rem .55rem; }

.book-detail__pager {
    display: flex; align-items: center; justify-content: space-between;
    gap: .5rem;
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--border-soft);
}
.book-detail__pager-btn {
    display: inline-flex; align-items: center;
    padding: .4rem .85rem;
    font-size: .85rem;
    color: var(--primary);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    text-decoration: none;
    transition: background .12s, border-color .12s;
}
.book-detail__pager-btn:hover {
    background: var(--surface-alt);
    border-color: var(--primary);
}
.book-detail__pager-btn[aria-disabled="true"] {
    opacity: .35;
    pointer-events: none;
}
.book-detail__pager-info {
    font-size: .82rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* === Book detail — sortable headers (server-side) =====================
 * The sales table opts out of admin-tables.js (data-no-equip) because the
 * dataset is paginated server-side; client-side sort would only reorder
 * the visible window. Headers are rendered as anchor links pointing at
 * the same URL with toggled sort/dir params; the panel JS intercepts
 * them via [data-book-detail-link] and re-fetches without a full nav. */
.book-detail__sales-table thead th {
    padding: 0;
}
.book-detail__sort-link {
    display: flex; align-items: center; justify-content: space-between;
    gap: .35rem;
    padding: .65rem .9rem;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    transition: background .12s;
}
.book-detail__sort-link:hover { background: var(--primary-dark); color: var(--bg); }
.book-detail__sort-arrow {
    font-size: .7rem;
    opacity: .55;
    color: inherit;
}
.book-detail__sales-table th.is-sorted .book-detail__sort-arrow {
    opacity: 1;
    color: var(--accent);
    font-weight: 700;
}

/* === Info popover next to settings labels =============================
 * Small "?" button anchored beside a field label. Reveals a contextual
 * explainer when clicked. Used e.g. for the commerce floor setting. */
.settings-label-with-info {
    position: relative;
    display: block;
}
.settings-label-with-info__text {
    display: inline-flex; align-items: center; gap: .35rem;
}
.settings-info-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    border-radius: 50%;
    transition: color .12s, background .12s;
}
.settings-info-btn:hover { color: var(--primary); background: var(--surface-alt); }
.settings-info-btn svg { width: 16px; height: 16px; }
.settings-info-popover {
    margin-top: .65rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border-left: 3px solid var(--accent);
    border-radius: 6px;
    font-size: .88rem;
    line-height: 1.5;
    color: var(--text);
}
.settings-info-popover h4 {
    margin: 0 0 .5rem;
    font-size: .82rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--primary);
}
.settings-info-popover p { margin: 0 0 .55rem; }
.settings-info-popover p:last-child { margin-bottom: 0; }
.settings-info-popover code {
    background: rgba(0,0,0,.06);
    padding: .05rem .35rem;
    border-radius: 3px;
    font-size: .85em;
}

/* === Ambassador detail panel (admin/ambassadeurs/{id}) ====================
 * Reuses the .sale-panel chrome; ambassador-specific layout below. */
.sale-panel__body [data-ambassador-detail] .ambassador-detail__head h1 {
    margin-top: 0;
    padding-right: 3rem;
}
.sale-panel__body [data-ambassador-detail] h1::after { display: none; }

.ambassador-detail__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
    padding-right: 3rem; /* room for the panel close button */
}
.ambassador-detail__head-body { min-width: 0; flex: 1; }
.ambassador-detail__head-body h1 { margin: .35rem 0 .25rem; font-size: 1.5rem; }
.ambassador-detail__email {
    margin: 0;
    color: var(--muted);
    font-size: .95rem;
}
.ambassador-detail__email a { color: inherit; text-decoration: underline dotted; }
.ambassador-detail__head-actions { flex-shrink: 0; }
.ambassador-detail__head-actions .btn {
    display: inline-flex; align-items: center; gap: .4rem;
}
.ambassador-detail__head-actions .btn svg { width: 14px; height: 14px; }

.ambassador-detail__commission-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .75rem;
}
.ambassador-detail__commission-card {
    display: flex; flex-direction: column; gap: .25rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
}
.ambassador-detail__commission-label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--muted);
    font-weight: 600;
}
.ambassador-detail__commission-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}
.ambassador-detail__commission-hint {
    font-size: .75rem;
    color: var(--muted);
    margin-top: .15rem;
}

.ambassador-detail__sales-table,
.ambassador-detail__codes-table {
    table-layout: fixed;
    width: 100%;
}
/* Sized for the panel viewport: date holds "DD/MM/YYYY HH:MM" + breathing
 * room, amount is right-aligned and tabular, status fits "Remboursé" with
 * margin from the panel edge. The Livre / Email columns flex on the rest. */
.ambassador-detail__col-date   { width: 9.75rem; }
.ambassador-detail__col-amount { width: 5.5rem; text-align: right; }
.ambassador-detail__col-status { width: 7rem; }

/* Ambassador dashboard — monthly history table: balanced column widths
 * (the month label no longer hogs the row; the three figure columns
 * share the remaining space evenly). */
.ambassador-dashboard__month-table { table-layout: fixed; }
.ambassador-dashboard__month-table th:first-child,
.ambassador-dashboard__month-table td:first-child { width: 28%; }
.ambassador-dashboard__col-num { width: 24%; text-align: right; }

/* === Ambassador lifecycle: stepper + next action + alerts === */
.ambassador-lifecycle { margin: 0 0 1.25rem; }
.ambassador-lifecycle__archived { color: var(--muted); font-style: italic; margin: 0 0 1rem; }
.ambassador-stepper {
    list-style: none; margin: 0 0 .9rem; padding: 0;
    display: flex; flex-wrap: wrap; gap: .25rem;
}
.ambassador-stepper__step {
    display: flex; align-items: center; gap: .45rem;
    flex: 1 1 auto; padding: .35rem .6rem; font-size: .82rem;
}
.ambassador-stepper__dot {
    flex: 0 0 auto; width: 1.5rem; height: 1.5rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: .8rem; font-weight: 700;
    background: var(--border); color: var(--surface);
}
.ambassador-stepper__label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ambassador-stepper__step.is-done    .ambassador-stepper__dot   { background: var(--primary); }
.ambassador-stepper__step.is-done    .ambassador-stepper__label { color: var(--muted); }
.ambassador-stepper__step.is-current .ambassador-stepper__dot   { background: var(--accent); }
.ambassador-stepper__step.is-current .ambassador-stepper__label { font-weight: 700; color: var(--text); }
.ambassador-stepper__step.is-error   .ambassador-stepper__dot   { background: #b3261e; }
.ambassador-stepper__step.is-error   .ambassador-stepper__label { font-weight: 700; color: #b3261e; }
.ambassador-stepper__step.is-todo    .ambassador-stepper__label { color: var(--muted); }
.ambassador-lifecycle__next {
    background: var(--surface-alt, rgba(0,0,0,.03));
    border: 1px solid var(--border); border-radius: var(--radius, 8px);
    padding: .6rem .85rem; margin: 0 0 .75rem;
    display: flex; flex-wrap: wrap; gap: .35rem 1.25rem; align-items: baseline;
}
.ambassador-lifecycle__next-action { margin: 0; font-size: .92rem; }
.ambassador-lifecycle__signature { margin: 0; font-size: .85rem; display: flex; gap: 1rem; flex-wrap: wrap; }
.ambassador-sig--done { color: var(--primary-dark, #2f6f4f); font-weight: 600; }
.ambassador-sig--wait { color: var(--muted); }
.ambassador-lifecycle__alert {
    margin: 0 0 .5rem; padding: .55rem .85rem;
    border-radius: var(--radius, 8px); font-size: .9rem; border: 1px solid;
}
.ambassador-lifecycle__alert--gold { background: rgba(201,162,39,.1); border-color: rgba(201,162,39,.4); }
.ambassador-lifecycle__alert--red  { background: rgba(179,38,30,.08); border-color: rgba(179,38,30,.35); color: #8a1f18; }

/* === Ambassador portal — onboarding progression === */
.ambassador-onboarding { margin: 1.5rem 0; }
.ambassador-onboarding__steps {
    list-style: none; margin: 0 0 1.5rem; padding: 0;
    display: flex; gap: .5rem; flex-wrap: wrap;
}
.ambassador-onboarding__step {
    flex: 1 1 140px;
    display: flex; flex-direction: column; align-items: center; gap: .45rem;
    text-align: center; padding: .5rem;
}
.ambassador-onboarding__dot {
    width: 2.25rem; height: 2.25rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-weight: 700;
    background: var(--border); color: var(--surface);
}
.ambassador-onboarding__label { font-size: .9rem; color: var(--muted); }
.ambassador-onboarding__step.is-done    .ambassador-onboarding__dot   { background: var(--primary); }
.ambassador-onboarding__step.is-current .ambassador-onboarding__dot   { background: var(--accent); }
.ambassador-onboarding__step.is-current .ambassador-onboarding__label { color: var(--text); font-weight: 700; }
.ambassador-onboarding__step.is-error   .ambassador-onboarding__dot   { background: #b3261e; }
.ambassador-onboarding__step.is-error   .ambassador-onboarding__label { color: #b3261e; font-weight: 700; }
.ambassador-onboarding__card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    padding: 1.5rem 1.75rem; text-align: center;
}
.ambassador-onboarding__card.is-error { border-color: rgba(179,38,30,.4); }
.ambassador-onboarding__card h2 { margin: 0 0 .5rem; }
.ambassador-onboarding__card p {
    margin: 0 auto 1rem; color: var(--muted); max-width: 540px;
}

/* === Portal info tooltip — tap/click the (i) to reveal a short note === */
.info-tip {
    position: relative;
    display: inline-block;
    vertical-align: middle;
    line-height: 1;       /* tight box: vertical-align then centres the actual
                             badge, not a line-box padded with empty space */
    margin-left: .35em;   /* breathing room from the preceding label text */
    top: -0.11em;         /* measured: cancels the ~1.5px x-height offset so the
                             badge sits on the text's centre */
}
.info-tip__btn {
    width: 1.1rem; height: 1.1rem; padding: 0;
    border: none; border-radius: 50%;
    background: var(--muted); color: var(--surface);
    font: 700 italic .72rem/1.1rem Georgia, serif;
    cursor: pointer;
}
.info-tip__btn:hover { background: var(--primary); }
.info-tip__bubble {
    display: none;
    position: absolute; left: 50%; transform: translateX(-50%);
    bottom: calc(100% + 9px);
    width: 250px; max-width: 76vw;
    background: #2a2a2a; color: #fff;
    font: 400 .8rem/1.45 inherit; font-style: normal; text-align: left;
    padding: .6rem .8rem; border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,.28);
    z-index: 60;
}
.info-tip.is-open .info-tip__bubble { display: block; }
.info-tip__bubble::after {
    content: ''; position: absolute; top: 100%; left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent; border-top-color: #2a2a2a;
}

/* === Portal "Comment suis-je payé ?" explainer === */
.ambassador-payinfo {
    margin: 1rem 0 0;
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    background: var(--surface);
}
.ambassador-payinfo > summary {
    cursor: pointer; padding: .8rem 1rem;
    font-weight: 600; color: var(--primary);
    list-style: none;
}
.ambassador-payinfo > summary::-webkit-details-marker { display: none; }
.ambassador-payinfo > summary::before { content: '💶 '; }
.ambassador-payinfo[open] > summary { border-bottom: 1px solid var(--border); }
.ambassador-payinfo__body { padding: .85rem 1.1rem; }
.ambassador-payinfo__body ol { margin: 0; padding-left: 1.2rem; }
.ambassador-payinfo__body li { margin: .4rem 0; line-height: 1.5; }

/* === Ambassador help page (workflow / glossary / FAQ) === */
.ambassador-help__flow { list-style: none; margin: 0; padding: 0; }
.ambassador-help__step {
    display: flex; align-items: flex-start; gap: .8rem;
    padding: .85rem 0;
    border-bottom: 1px solid var(--border);
}
.ambassador-help__step:last-child { border-bottom: none; }
.ambassador-help__step-num {
    flex: 0 0 auto;
    width: 1.7rem; height: 1.7rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--primary); color: var(--surface);
    font-weight: 700; font-size: .85rem;
}
.ambassador-help__step-icon { flex: 0 0 auto; font-size: 1.5rem; line-height: 1.5; }
.ambassador-help__step-body { display: flex; flex-direction: column; gap: .15rem; }
.ambassador-help__step-body strong { color: var(--text); }
.ambassador-help__step-body span { color: var(--muted); font-size: .92rem; line-height: 1.5; }
.ambassador-help__glossary { margin: 0; }
.ambassador-help__glossary dt { font-weight: 700; color: var(--primary); margin-top: .85rem; }
.ambassador-help__glossary dt:first-child { margin-top: 0; }
.ambassador-help__glossary dd {
    margin: .15rem 0 0; color: var(--muted); font-size: .92rem; line-height: 1.5;
}
.ambassador-help__faq { border-bottom: 1px solid var(--border); }
.ambassador-help__faq > summary {
    cursor: pointer; padding: .75rem 0; font-weight: 600; list-style: none;
    display: flex; justify-content: space-between; align-items: center; gap: 1rem;
}
.ambassador-help__faq > summary::-webkit-details-marker { display: none; }
.ambassador-help__faq > summary::after { content: '+'; color: var(--muted); font-size: 1.2rem; }
.ambassador-help__faq[open] > summary::after { content: '\2212'; }
.ambassador-help__faq > p {
    margin: 0 0 .85rem; color: var(--muted); font-size: .92rem; line-height: 1.55;
}
.ambassador-help__contact { text-align: center; }

/* === Ambassador profile completion bar + milestones === */
.profile-completion {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    padding: 1.1rem 1.25rem;
    margin: 0 0 1.5rem;
}
.profile-completion__head {
    display: flex; justify-content: space-between; align-items: baseline;
    flex-wrap: wrap; gap: .5rem; margin-bottom: .6rem;
}
.profile-completion__head h2 { margin: 0; font-size: 1.1rem; }
.profile-completion__count { color: var(--muted); font-size: .9rem; font-weight: 600; }
.profile-completion__bar {
    height: 8px; border-radius: 999px;
    background: var(--border); overflow: hidden; margin-bottom: 1rem;
}
.profile-completion__bar-fill {
    display: block; height: 100%;
    background: var(--primary); transition: width .3s ease;
}
.profile-completion__milestones { list-style: none; margin: 0; padding: 0; }
.profile-completion__milestone {
    display: flex; gap: .65rem; align-items: flex-start;
    padding: .55rem 0; border-top: 1px solid var(--border);
}
.profile-completion__milestone:first-child { border-top: none; }
.profile-completion__milestone-icon {
    flex: 0 0 auto; width: 1.5rem; height: 1.5rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: .85rem;
    background: var(--surface-alt, rgba(0,0,0,.05));
}
.profile-completion__milestone.is-done .profile-completion__milestone-icon {
    background: var(--primary); color: var(--surface); font-weight: 700;
}
.profile-completion__milestone-body { display: flex; flex-direction: column; gap: .1rem; }
.profile-completion__milestone-body strong { color: var(--text); }
.profile-completion__milestone.is-done .profile-completion__milestone-body strong { color: var(--muted); }
.profile-completion__milestone-desc { color: var(--muted); font-size: .88rem; line-height: 1.45; }
.profile-completion__milestone-missing {
    color: #8a1f18; font-size: .88rem; font-weight: 600; margin-top: .1rem;
}
.profile-completion__milestone.is-locked { opacity: .5; }
.profile-completion__milestone-next {
    color: var(--muted); font-size: .82rem; font-style: italic; margin-top: .1rem;
}

/* === Dashboard onboarding — "action requise" alert === */
.ambassador-onboarding__alert {
    margin-top: 1rem;
    background: rgba(201,162,39,.1);
    border: 1px solid rgba(201,162,39,.45);
    border-radius: var(--radius, 10px);
    padding: 1rem 1.15rem;
}
.ambassador-onboarding__alert strong { display: block; margin-bottom: .25rem; }
.ambassador-onboarding__alert p { margin: 0 0 .75rem; color: var(--text); line-height: 1.5; }
.ambassador-detail__col-book   { /* flex */ }
.ambassador-detail__sales-table th,
.ambassador-detail__sales-table td,
.ambassador-detail__codes-table th,
.ambassador-detail__codes-table td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Last column gets explicit right padding so the status badge doesn't
 * butt up against the table's outer border. */
.ambassador-detail__sales-table th:last-child,
.ambassador-detail__sales-table td:last-child,
.ambassador-detail__codes-table th:last-child,
.ambassador-detail__codes-table td:last-child {
    padding-right: 1rem;
}
.ambassador-detail__cell-truncate { direction: ltr; }

/* Codes table — 6 columns including an actions column (toggle / edit /
 * delete). It cannot fit a narrow ambassador panel, and the shared cell rule
 * above (overflow:hidden) was cropping the action buttons. Let this table
 * size to its content and scroll horizontally inside the panel instead. */
.ambassador-detail__codes-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.ambassador-detail__codes-table {
    table-layout: auto;
    min-width: 100%;
}
.ambassador-detail__codes-table th,
.ambassador-detail__codes-table td {
    overflow: visible;
    text-overflow: clip;
}
/* Action buttons stay on a single row; the column widens to fit them. */
.ambassador-detail__codes-actions {
    display: flex;
    gap: .4rem;
    align-items: flex-start;
    flex-wrap: nowrap;
}
/* Inline edit panel for a code, revealed by the <details> "Éditer" toggle. */
.ambassador-detail__code-edit > summary { cursor: pointer; }
.ambassador-detail__code-edit[open] > summary { margin-bottom: .5rem; }
.ambassador-detail__code-edit-form {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    min-width: 13rem;
    padding: .65rem .75rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-alt, rgba(0, 0, 0, .03));
}

.ambassador-sale-row,
.ambassador-detail__code-row {
    cursor: pointer;
    transition: background-color .12s ease;
}
.ambassador-sale-row:hover,
.ambassador-detail__code-row:hover {
    background: var(--surface-alt, rgba(0,0,0,.03));
}
.ambassador-sale-row:focus-visible,
.ambassador-detail__code-row:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

/* === Ambassador detail — tabbed layout =================================
 * The panel hosts 4 tabs (Synthèse / Informations / Commissions / Compta).
 * Tab nav is sticky-ish at the top of the panel body; only the active
 * pane is rendered visible to keep DOM cost low even with rate history
 * + payouts + invoices + documents loaded simultaneously. */
.ambassador-detail__tabs {
    display: flex;
    gap: .25rem;
    margin: 0 0 1.25rem;
    padding-bottom: .25rem;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
}
.ambassador-detail__tab {
    appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    padding: .5rem .9rem;
    font-size: .9rem;
    font-weight: 500;
    color: var(--muted);
    cursor: pointer;
    transition: color .12s, border-color .12s;
    white-space: nowrap;
}
.ambassador-detail__tab:hover { color: var(--text); }
.ambassador-detail__tab.is-active {
    color: var(--primary);
    border-bottom-color: var(--accent);
    font-weight: 600;
}
.ambassador-detail__pane { display: none; }
.ambassador-detail__pane.is-active { display: block; }

/* Inline alert banner (legal block missing, late payout, etc.). */
.ambassador-detail__alert {
    margin: 0 0 1.25rem;
    padding: .85rem 1rem;
    border-radius: 8px;
    font-size: .92rem;
}
.ambassador-detail__alert--warn {
    background: #fff8e6;
    border-left: 3px solid #d4a017;
    color: #5c4500;
}
.ambassador-detail__alert strong { color: inherit; }

/* KPI grid on the Synthèse tab — auto-fit so cards stay readable on
 * narrow panels. */
.ambassador-detail__kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .75rem;
    margin-bottom: 1.25rem;
}
.ambassador-detail__kpi {
    display: flex; flex-direction: column; gap: .15rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
}
.ambassador-detail__kpi--muted { opacity: .6; }
.ambassador-detail__kpi-label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--muted);
    font-weight: 600;
}
.ambassador-detail__kpi-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.ambassador-detail__kpi-hint {
    font-size: .75rem;
    color: var(--muted);
    margin-top: .15rem;
}

/* Promo chips on the Synthèse tab — at-a-glance overview of which codes
 * lead back to this ambassador. */
.ambassador-detail__code-chips {
    display: flex; flex-wrap: wrap; gap: .5rem;
}
.ambassador-detail__code-chip {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .35rem .65rem;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: .85rem;
    color: var(--text);
    text-decoration: none;
    transition: background .12s;
}
.ambassador-detail__code-chip:hover { background: var(--surface); border-color: var(--primary); }
.ambassador-detail__code-chip code {
    font-family: var(--font-mono, ui-monospace, monospace);
    background: rgba(45, 80, 64, .12);
    padding: .1rem .4rem;
    border-radius: 4px;
}

/* === Ambassador detail — payouts/documents/modal styling ================= */
.ambassador-detail__kpi--accent {
    background: color-mix(in srgb, var(--accent) 12%, var(--surface) 88%);
    border-color: var(--accent);
}
.ambassador-detail__kpi--accent .ambassador-detail__kpi-value { color: var(--primary-dark); }

.ambassador-detail__alert--danger {
    background: #fdecec;
    border-left: 3px solid var(--danger, #b94a48);
    color: #6c1f1f;
}

.ambassador-detail__row--voided {
    opacity: .55;
    text-decoration: line-through;
}
.ambassador-detail__row--voided td:first-child,
.ambassador-detail__row--voided td:last-child { text-decoration: none; }

.ambassador-detail__payouts-table th,
.ambassador-detail__payouts-table td {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Modal dialogs — used for payout recording + doc upload. Mirrors the
 * favicon-crop modal chrome (same project conventions). */
.ambassador-modal {
    border: 0;
    padding: 0;
    border-radius: 14px;
    width: min(640px, calc(100vw - 2rem));
    max-width: none;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 24px 60px rgba(27, 58, 42, .35), 0 4px 12px rgba(0, 0, 0, .08);
    margin: auto;
}
.ambassador-modal::backdrop { background: rgba(27, 58, 42, .55); backdrop-filter: blur(2px); }
.ambassador-modal__head {
    display: flex; align-items: center; justify-content: space-between;
    padding: .9rem 1.25rem;
    background: var(--primary);
    color: var(--surface);
}
.ambassador-modal__head h2 {
    font-size: 1.05rem; margin: 0; color: inherit; font-weight: 600;
    text-transform: none; letter-spacing: 0;
}
.ambassador-modal__close {
    background: none; border: 0; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: inherit;
    padding: 0 .25rem; opacity: .85;
}
.ambassador-modal__close:hover { opacity: 1; }
.ambassador-modal__body { padding: 1.25rem; }
.ambassador-modal__foot {
    display: flex; justify-content: flex-end; gap: .6rem;
    padding: .85rem 1.25rem;
    background: var(--surface-alt, #f7f4ec);
    border-top: 1px solid var(--border);
}
.ambassador-modal__balance {
    background: color-mix(in srgb, var(--accent) 12%, var(--surface) 88%);
    border-left: 3px solid var(--accent);
    padding: .55rem .85rem;
    border-radius: 6px;
    font-size: .92rem;
    margin-bottom: 1rem;
}

.btn-link {
    background: transparent; border: 0; padding: 0;
    cursor: pointer; text-decoration: underline;
}

/* Inline-aligned monospace pill — neutralises the `<code>` block padding
 * so that SIRET/IBAN values sit on the same baseline as the plain text
 * values in adjacent rows. The original `<code>` styling pushed the
 * cell content downward visually because of its background + padding. */
.detail-table .detail-mono {
    display: inline;
    background: rgba(45, 80, 64, .08);
    padding: .08em .4em;
    border-radius: 4px;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: .92em;
    /* Match the line-height of the surrounding text — without this the
     * baseline visually slips because the default <code> sets height. */
    line-height: inherit;
    vertical-align: baseline;
}

.ambassador-detail__proof-cell {
    display: inline-flex; align-items: center; gap: .5rem;
    white-space: nowrap;
}
.ambassador-detail__proof-btn {
    color: var(--primary);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.ambassador-detail__proof-btn:hover { color: var(--primary-dark); }

/* === Ambassador detail — commission rate timeline ========================
 * Vertical timeline showing the ambassador's rate changes over time. The
 * current slice (effective_to IS NULL) gets the accent treatment so the
 * "where we are now" is unmistakable. */
.ambassador-detail__timeline {
    list-style: none;
    margin: 0; padding: 0;
    position: relative;
}
.ambassador-detail__timeline::before {
    content: '';
    position: absolute;
    left: 11px; top: 6px; bottom: 6px;
    width: 2px;
    background: var(--border);
}
.ambassador-detail__timeline-item {
    position: relative;
    padding-left: 2.25rem;
    padding-bottom: 1.1rem;
}
.ambassador-detail__timeline-item:last-child { padding-bottom: 0; }
.ambassador-detail__timeline-marker {
    position: absolute;
    left: 5px; top: 8px;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--surface);
    border: 2px solid var(--border);
    z-index: 1;
}
.ambassador-detail__timeline-item.is-current .ambassador-detail__timeline-marker {
    background: var(--accent);
    border-color: var(--accent);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent);
}
.ambassador-detail__timeline-head {
    display: flex; align-items: baseline; gap: .5rem;
    flex-wrap: wrap;
    margin-bottom: .15rem;
}
.ambassador-detail__timeline-rate {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}
.ambassador-detail__timeline-item:not(.is-current) .ambassador-detail__timeline-rate {
    color: var(--muted);
}
.ambassador-detail__timeline-pill {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    background: var(--accent);
    color: var(--surface);
    padding: .12rem .55rem;
    border-radius: 999px;
    font-weight: 700;
}
.ambassador-detail__timeline-period {
    font-size: .88rem;
    color: var(--text);
    margin-bottom: .2rem;
}
.ambassador-detail__timeline-period strong { font-feature-settings: "tnum"; }
.ambassador-detail__timeline-note {
    font-size: .85rem;
    color: var(--muted);
    font-style: italic;
}

/* === Ambassador Compta tab — header CTA + payouts table polish ============ */
.ambassador-compta__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; margin-bottom: .85rem;
}
.ambassador-compta__cta {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .5rem .9rem;
    font-size: .9rem;
    white-space: nowrap;
    flex-shrink: 0;
}
.ambassador-compta__cta-icon { width: 14px; height: 14px; flex-shrink: 0; }

.ambassador-detail__payouts-table { table-layout: fixed; width: 100%; }
/* Percentage widths so the table re-balances itself at every panel size
 * (the panel is much wider in fullscreen than in mobile-narrow). The
 * previous mix of fixed rem widths with ONE auto column gave the auto
 * column all the slack on a wide screen, blowing out Méthode. */
.ambassador-compta__col-date    { width: 20%; }
.ambassador-compta__col-amount  { width: 16%; text-align: right; }
.ambassador-compta__col-method  { width: 24%; }
.ambassador-compta__col-docs    { width: 28%; }
.ambassador-compta__col-actions { width: 12%; text-align: right; }

/* Méthode cells with a payment reference: dotted underline + cursor:help
 * + a CSS-only tooltip that appears instantly on hover. We don't rely
 * on the browser's native title= because the delay (500-1500ms) makes
 * users think nothing happens. */
.ambassador-compta__method-with-ref {
    position: relative;
    text-decoration: underline dotted;
    text-decoration-color: var(--muted);
    text-underline-offset: 3px;
    cursor: help;
}
.ambassador-compta__method-with-ref::after {
    content: attr(data-tip);
    position: absolute;
    left: 0;
    top: calc(100% + 8px);
    background: var(--primary);
    color: var(--surface);
    padding: .35rem .65rem;
    border-radius: 6px;
    font-size: .78rem;
    font-weight: 500;
    white-space: nowrap;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .2);
    opacity: 0;
    pointer-events: none;
    transition: opacity .12s ease;
    z-index: 100;
}
/* Tooltip arrow pointing UP to the word above. We anchor the tooltip
 * BELOW the cell by default because the row's neighbours (and any
 * potential overflow clipping above) would crop a tooltip rendered
 * above. The last-rows override below flips it back to "above" when
 * there's no room below. */
.ambassador-compta__method-with-ref::before {
    content: '';
    position: absolute;
    left: 1.25rem;
    top: calc(100% + 3px);
    border: 5px solid transparent;
    border-bottom-color: var(--primary);
    opacity: 0;
    pointer-events: none;
    transition: opacity .12s ease;
    z-index: 100;
}
.ambassador-compta__method-with-ref:hover::after,
.ambassador-compta__method-with-ref:hover::before,
.ambassador-compta__method-with-ref:focus::after,
.ambassador-compta__method-with-ref:focus::before {
    opacity: 1;
}

/* Last row(s) of the payouts table — flip the tooltip ABOVE the word
 * because the section bottom edge clips a tooltip pointing down. The
 * rows above always have a table header / earlier row so an upward
 * tooltip stays visible. We cover the last 2 rows so a 1-row table
 * also flips properly. */
.ambassador-detail__payouts-table tbody tr:nth-last-child(-n+2) .ambassador-compta__method-with-ref::after {
    top: auto;
    bottom: calc(100% + 8px);
}
.ambassador-detail__payouts-table tbody tr:nth-last-child(-n+2) .ambassador-compta__method-with-ref::before {
    top: auto;
    bottom: calc(100% + 3px);
    border-bottom-color: transparent;
    border-top-color: var(--primary);
}
.ambassador-detail__payouts-table th,
.ambassador-detail__payouts-table td {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    vertical-align: middle;
    padding: .55rem .5rem;
}
/* The "Documents" column needs to keep its inline-flex children visible
 * — re-enabling overflow so the icon row isn't clipped when the column
 * is narrow on a narrow panel. */
.ambassador-detail__payouts-table td.ambassador-compta__col-docs,
/* Méthode cell: same opt-out so the hover tooltip pseudo-element above
 * the underlined word can escape the cell box (the default cell
 * overflow:hidden was clipping it). */
.ambassador-detail__payouts-table td.ambassador-compta__col-method {
    overflow: visible; text-overflow: clip;
}
.ambassador-detail__payouts-table .ambassador-compta__col-method small { display: block; }

/* SVG icons in the Documents column — uniform line-icon size + hover. */
.ambassador-compta__doc-icons {
    display: inline-flex; align-items: center; gap: .25rem;
}
.ambassador-compta__doc-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px;
    border-radius: 6px;
    color: var(--muted);
    text-decoration: none;
    transition: color .12s, background .12s;
    /* Same class on <a> (invoice link) and <button> (proof viewer
     * trigger) — strip the button chrome so they match visually. */
    appearance: none;
    background: transparent;
    border: 0;
    cursor: pointer;
    padding: 0;
}
.ambassador-compta__doc-icon svg { width: 16px; height: 16px; }
.ambassador-compta__doc-icon:hover { color: var(--primary); background: var(--surface-alt); }

/* Action button: stronger visual weight at rest so the operator spots
 * it immediately when scanning the row (the user explicitly asked for
 * the actions to be prioritised). Solid border, accent-tinted bg. */
.ambassador-compta__doc-add {
    appearance: none;
    width: 28px; height: 28px;
    border: 1px solid var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border-radius: 6px;
    color: var(--primary-dark);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: color .12s, background .12s, border-color .12s;
    padding: 0;
}
.ambassador-compta__doc-add svg { width: 14px; height: 14px; }
.ambassador-compta__doc-add:hover {
    background: var(--accent);
    color: var(--surface);
}

/* Cancel-payout icon button: still subtle by default (destructive but
 * rarely used) but visible enough to notice — outlined ghost style. */
.ambassador-compta__void-btn {
    appearance: none;
    background: transparent;
    border: 1px solid var(--border);
    width: 28px; height: 28px;
    border-radius: 50%;
    color: var(--muted);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: color .12s, background .12s, border-color .12s;
    padding: 0;
}
.ambassador-compta__void-btn svg { width: 16px; height: 16px; }
.ambassador-compta__void-btn:hover {
    color: var(--danger, #b94a48);
    border-color: var(--danger, #b94a48);
    background: color-mix(in srgb, var(--danger, #b94a48) 12%, transparent);
}

/* === Ambassador modals — styled dropzone file input ====================
 * Replaces the native <input type="file"> chrome (which clashes hard
 * with the rest of the modal) by a click-anywhere dashed area. The
 * underlying input is visually hidden but still in the form, so the
 * submit ships the file unchanged. Drag-and-drop is wired by JS. */
.ambassador-dropzone-field {
    display: flex; flex-direction: column; gap: .35rem;
}
.ambassador-dropzone-field__label {
    font-size: .85rem;
    font-weight: 600;
    color: var(--text);
}
.ambassador-dropzone {
    position: relative;
    display: flex; align-items: center; gap: .85rem;
    padding: .85rem 1rem;
    border: 1.5px dashed var(--border);
    border-radius: 10px;
    background: var(--surface-alt);
    cursor: pointer;
    transition: border-color .15s, background .15s;
}
.ambassador-dropzone:hover,
.ambassador-dropzone:focus-within {
    border-color: var(--primary);
    background: var(--surface);
}
.ambassador-dropzone.is-dragging {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 12%, var(--surface) 88%);
}
.ambassador-dropzone.has-file {
    border-style: solid;
    border-color: var(--primary);
    background: var(--surface);
}
.ambassador-dropzone__input {
    /* Visually hidden but still focusable + ships the file. */
    position: absolute;
    opacity: 0;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}
.ambassador-dropzone__icon {
    width: 28px; height: 28px;
    color: var(--muted);
    flex-shrink: 0;
}
.ambassador-dropzone.has-file .ambassador-dropzone__icon { color: var(--primary); }
.ambassador-dropzone__text {
    display: flex; flex-direction: column; gap: .15rem;
    min-width: 0; flex: 1;
}
.ambassador-dropzone__text strong {
    font-size: .92rem;
    color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ambassador-dropzone__text span {
    font-size: .78rem;
    color: var(--muted);
}

/* === Contract section — header actions + signed-version sign form === */
.ambassador-contract__actions {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
    align-items: center;
}
.ambassador-contract__sign-form {
    margin-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .85rem;
    align-items: stretch;
}
.ambassador-contract__sign-form .btn {
    align-self: flex-start;
}
.ambassador-contract__history {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px dashed var(--border);
}
.ambassador-contract__history > summary {
    cursor: pointer;
    font-size: .9rem;
    font-weight: 600;
    color: var(--muted);
    user-select: none;
    list-style: revert;
}
.ambassador-contract__history > summary:hover {
    color: var(--text);
}
.ambassador-contract__history-table {
    margin-top: .85rem;
    font-size: .9rem;
}

/* === "À traiter" banner on /admin/ambassadeurs =========================
 * Surfaces ambassadors with a positive balance + last payout > 60 days
 * (or never), so the admin doesn't have to leave the list to /compta to
 * notice an overdue settlement. */
.ambassador-todo-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap; /* narrow screens: "Aller à la comptabilité" wraps below */
    gap: .65rem;
    padding: .85rem 1.1rem;
    margin: 0 0 1.25rem;
    background: #fff8eb;
    border: 1px solid #e3c55a;
    border-radius: 10px;
    color: var(--text);
    font-size: .92rem;
    text-decoration: none;
    transition: background .15s, border-color .15s;
}
.ambassador-todo-banner:hover { background: #fff2d4; border-color: #c9a227; }
.ambassador-todo-banner svg   { width: 18px; height: 18px; color: #c9a227; flex-shrink: 0; }
.ambassador-todo-banner strong { color: var(--text); }

/* === Ambassador dashboard chart tooltip ================================
 * Pinned to the cursor on hover of any [data-bar]. Inline JS in the
 * dashboard view positions it (clientX/Y + scroll). Z-index above
 * the page so it never gets clipped by section padding. */
.ambassador-chart-tooltip {
    position: absolute;
    z-index: 50;
    pointer-events: none;
    background: var(--text);
    color: var(--bg);
    padding: .55rem .75rem;
    border-radius: 6px;
    font-size: .82rem;
    line-height: 1.45;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
    white-space: nowrap;
    transform: translate(0, -100%);
}
.ambassador-chart-tooltip strong {
    text-transform: capitalize;
    font-weight: 600;
}
.ambassador-chart-tooltip__amount {
    color: #d9b94d;
    font-weight: 600;
}
/* Hover band on the chart: subtle highlight on the slot the cursor is
 * over, to confirm interactivity. */
svg [data-bar]:hover {
    fill: rgba(201, 162, 39, .08);
}

/* === Documents joints — open-in-viewer button (looks like a link) ==== */
.ambassador-document__open {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    color: var(--primary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font: inherit;
    text-align: left;
}
.ambassador-document__open:hover { text-decoration: underline; }
.ambassador-document__open svg   { width: 14px; height: 14px; flex-shrink: 0; }

/* === Document viewer modal — justificatif, facture, ... ============== */
.ambassador-modal--viewer {
    width: min(900px, calc(100vw - 2rem));
}
.ambassador-modal__viewer-body {
    padding: 0;
    background: #2b2b2b;
    min-height: 60vh;
    max-height: 75vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: auto;
}
.ambassador-modal__viewer-frame {
    width: 100%;
    height: 75vh;
    border: 0;
    background: #fff;
    display: block;
}
.ambassador-modal__viewer-img {
    max-width: 100%;
    max-height: 75vh;
    width: auto;
    height: auto;
    display: block;
    object-fit: contain;
}

/* === Onboarding — setup gate ============================================ */

/* Persistent banner below the header while the configuration is incomplete. */
.admin-setup-banner {
    display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: .25rem 1rem;
    background: rgba(201, 162, 39, .14);
    border-bottom: 1px solid rgba(201, 162, 39, .5);
    color: var(--text);
    padding: .7rem 1.25rem;
    font-size: .92rem;
    text-align: center;
}
.admin-setup-banner a {
    color: var(--primary-dark, var(--primary));
    font-weight: 700;
    white-space: nowrap;
}

/* Onboarding dashboard — intro block + CTA. */
.onboarding-intro { max-width: 720px; margin: 0 0 1.5rem; }
.onboarding-intro h1 { margin: 0 0 .5rem; }
.onboarding-intro p { color: var(--muted); line-height: 1.55; margin: 0; }
.onboarding-cta { margin: 1.1rem 0 0; }

/* .env pre-flight diagnostic card. */
.setup-preflight {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    padding: 1.1rem 1.25rem;
    margin: 1.5rem 0 0;
}
.setup-preflight h2 { margin: 0 0 .35rem; font-size: 1.1rem; }
.setup-preflight__intro { color: var(--muted); font-size: .9rem; line-height: 1.5; margin: 0 0 .9rem; }
.setup-preflight__intro code,
.setup-preflight__body code {
    background: var(--surface-alt, rgba(0,0,0,.05));
    border-radius: 4px; padding: .05rem .35rem; font-size: .85em;
}
.setup-preflight__list { list-style: none; margin: 0; padding: 0; }
.setup-preflight__item {
    display: flex; gap: .65rem; align-items: flex-start;
    padding: .55rem 0; border-top: 1px solid var(--border);
}
.setup-preflight__item:first-child { border-top: none; }
.setup-preflight__mark {
    flex: 0 0 auto; width: 1.4rem; height: 1.4rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: .8rem; font-weight: 700;
}
.setup-preflight__item.is-ok  .setup-preflight__mark { background: var(--primary); color: var(--surface); }
.setup-preflight__item.is-ko  .setup-preflight__mark { background: #b3261e; color: #fff; }
.setup-preflight__body { display: flex; flex-direction: column; gap: .15rem; }
.setup-preflight__body strong { color: var(--text); }
.setup-preflight__body code { align-self: flex-start; }
.setup-preflight__hint { color: var(--muted); font-size: .86rem; line-height: 1.45; }

/* === VAT franchise alert (dashboard) ==================================== */
.vat-alert {
    border-radius: var(--radius, 10px);
    border: 1px solid;
    padding: .9rem 1.15rem;
    margin: 0 0 1.5rem;
}
.vat-alert strong { display: block; }
.vat-alert p { margin: .25rem 0 0; font-size: .92rem; line-height: 1.5; }
.vat-alert--warning {
    background: rgba(201, 162, 39, .12);
    border-color: rgba(201, 162, 39, .55);
}
.vat-alert--exceeded {
    background: rgba(179, 38, 30, .09);
    border-color: rgba(179, 38, 30, .45);
}
.vat-alert--exceeded strong { color: #b3261e; }

/* ======================================================================
 * Book detail panel — dashboard-style layout
 * ======================================================================
 * Replaces the old single "Détails" table + flat sales summary. Sections
 * each fit on one screen of the slide-in panel; the KPI strip is the at-
 * a-glance landing surface, every following block is a navigable summary
 * card with a "Modifier le …" deep-link to the right tab of the edit form.
 */
.book-detail__meta-line {
    margin: 0;
    color: var(--muted);
    font-size: .82rem;
}

.book-detail__kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: .65rem;
    margin: 0 0 1.5rem;
}
.book-detail__kpi {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    padding: .65rem .85rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    min-width: 0;
}
.book-detail__kpi-label {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    font-weight: 600;
}
.book-detail__kpi-value {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--primary);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.book-detail__kpi-flag {
    display: block;
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-top: .1rem;
}
.book-detail__kpi--warn {
    background: rgba(201, 162, 39, .12);
    border-color: rgba(201, 162, 39, .45);
}
.book-detail__kpi--warn .book-detail__kpi-value,
.book-detail__kpi--warn .book-detail__kpi-flag { color: #7a5e0f; }
.book-detail__kpi--alert {
    background: rgba(179, 38, 30, .09);
    border-color: rgba(179, 38, 30, .45);
}
.book-detail__kpi--alert .book-detail__kpi-value,
.book-detail__kpi--alert .book-detail__kpi-flag { color: #b3261e; }

.book-detail__block {
    margin: 0 0 1.5rem;
    padding: 0;
}
.book-detail__block-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin: 0 0 .65rem;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--border-soft);
}
.book-detail__block-head h2 {
    margin: 0;
    font-size: 1.05rem;
}
.book-detail__block-edit {
    font-size: .82rem;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
}
.book-detail__block-edit:hover { text-decoration: underline; }

.book-detail__dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 1rem;
    row-gap: .35rem;
    margin: 0;
    font-size: .9rem;
}
.book-detail__dl dt {
    color: var(--muted);
    font-weight: 600;
}
.book-detail__dl dd {
    margin: 0;
    color: var(--text);
    overflow-wrap: anywhere;
}
.book-detail__dl code {
    background: var(--surface-alt);
    padding: 0 .3rem;
    border-radius: 4px;
    font-size: .85em;
}

.book-detail__resources {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}
.book-detail__resources li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .45rem .65rem;
    background: var(--surface-alt);
    border-radius: 6px;
    font-size: .9rem;
}
.book-detail__resources li > :first-child {
    font-weight: 600;
    color: var(--text);
}
.book-detail__resources li a { color: var(--primary); text-decoration: none; }
.book-detail__resources li a:hover { text-decoration: underline; }
.book-detail__resources li > :last-child {
    color: var(--muted);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.book-detail__resources li code {
    background: transparent;
    color: var(--muted);
    font-size: .85em;
}

.book-detail__hint {
    margin: .5rem 0 0;
    font-size: .85rem;
    color: var(--muted);
    line-height: 1.5;
}
.book-detail__hint--warn {
    color: #7a5e0f;
    background: rgba(201, 162, 39, .12);
    border-left: 3px solid rgba(201, 162, 39, .55);
    padding: .55rem .75rem;
    border-radius: 0 6px 6px 0;
}

.book-detail__foot {
    margin-top: 2rem;
    padding-top: .85rem;
    border-top: 1px solid var(--border-soft);
    font-size: .78rem;
    color: var(--muted);
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    align-items: center;
}
.book-detail__foot a {
    color: var(--primary);
    text-decoration: none;
}
.book-detail__foot a:hover { text-decoration: underline; }

/* ======================================================================
 * Admin books list — richer columns (cover thumb, format chips, stock,
 * completeness flag).
 * ====================================================================== */
.books-list { table-layout: auto; }
.books-list__col-cover   { width: 56px; }
.books-list__col-format  { width: 8rem; }
.books-list__col-status  { width: 7rem; }
.books-list__col-price   { width: 7rem; text-align: right; }
.books-list__col-stock   { width: 5rem; text-align: right; }
.books-list__col-release { width: 8.5rem; }
.books-list__col-ready   { width: 4rem; text-align: center; }

.books-list__cell-cover { padding: .4rem .3rem .4rem .9rem; }
.books-list__cover {
    display: block;
    width: 36px; height: 54px;
    object-fit: cover;
    border-radius: 3px;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
}
.books-list__cover--placeholder {
    background: repeating-linear-gradient(
        45deg,
        var(--surface-alt) 0 4px,
        rgba(0,0,0,.04) 4px 8px
    );
}
.books-list__subtitle {
    font-size: .8rem;
    font-style: italic;
    margin-top: .15rem;
}
.books-list__format-chip {
    display: inline-block;
    padding: .1rem .45rem;
    border-radius: 4px;
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    line-height: 1.5;
    margin-right: .2rem;
}
.books-list__format-chip--digital {
    background: rgba(59, 130, 246, .12);
    color: #1e40af;
}
.books-list__format-chip--physical {
    background: rgba(217, 119, 6, .15);
    color: #92400e;
}
.books-list__cell-price div { font-variant-numeric: tabular-nums; }
.books-list__cell-price .muted { font-size: .8rem; }
.books-list__cell-stock { font-variant-numeric: tabular-nums; }
.books-list__stock small {
    display: block;
    font-size: .7rem;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.books-list__stock--low { color: #7a5e0f; font-weight: 600; }
.books-list__stock--low small { color: #7a5e0f; }
.books-list__stock--out { color: #b3261e; font-weight: 700; }
.books-list__stock--out small { color: #b3261e; }

.books-list__ready {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.8rem;
    height: 1.5rem;
    border-radius: 12px;
    font-size: .8rem;
    font-weight: 700;
    padding: 0 .5rem;
    cursor: help;
}
.books-list__ready--ok {
    background: rgba(4, 120, 87, .16);
    color: #065f46;
}
.books-list__ready--ko {
    background: rgba(201, 162, 39, .2);
    color: #7a5e0f;
}

/* ======================================================================
 * Book form — overview pane (apercu)
 * ====================================================================== */
.form-overview-checklist {
    margin: 0 0 1.5rem;
    padding: 1rem 1.15rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 10px;
}
.form-overview-checklist h3 {
    margin: 0 0 .5rem;
    font-size: 1rem;
}
.form-overview-checklist__ok {
    margin: 0;
    color: #065f46;
    font-weight: 600;
}
.form-overview-checklist__intro {
    margin: 0 0 .65rem;
    color: var(--muted);
    font-size: .9rem;
}
.form-overview-checklist__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .4rem;
}
.form-overview-checklist__list li {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .45rem .65rem;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    font-size: .9rem;
}
.form-overview-checklist__icon {
    color: #7a5e0f;
    font-weight: 700;
}
.form-overview-checklist__label { flex: 1; min-width: 0; }
.form-overview-checklist__jump {
    color: var(--primary);
    text-decoration: none;
    font-size: .82rem;
    white-space: nowrap;
}
.form-overview-checklist__jump:hover { text-decoration: underline; }

.form-section-rule {
    border: 0;
    border-top: 1px solid var(--border-soft);
    margin: 1.5rem 0 .25rem;
}

.archive-form {
    background: rgba(179, 38, 30, .04);
    border: 1px solid rgba(179, 38, 30, .25);
    border-radius: 8px;
    padding: 1rem 1.15rem;
    margin: 0;
}

/* Native <fieldset> styling reset for the physical-edition block + faded
 * look when the "Édition papier" toggle is off. `disabled` is set by JS in
 * book-form.php to actually prevent input, and we mirror it visually. */
.physical-block {
    border: 0;
    padding: 0;
    margin: 0;
    min-inline-size: 0;
}
.physical-block[disabled] {
    opacity: .45;
    pointer-events: none;
    filter: grayscale(.4);
}

.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* =====================================================================
   Tracking dashboard — /admin/ventes/expeditions
   Cards-of-shipments view with a 4-step progress bar coloured by parcel
   age (green < 5 j, orange 5–10 j, red > 10 j). Reads the cron-maintained
   snapshot from purchase_shipments; the "Rafraîchir" button forces a poll.
   ===================================================================== */
.shipments-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
    gap: 1rem;
}
.shipment-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-left: 4px solid var(--primary); /* tone strip — overridden per tone below */
    border-radius: var(--radius);
    padding: 1rem 1.1rem;
    box-shadow: var(--shadow-sm);
    display: flex; flex-direction: column; gap: .85rem;
    min-width: 0;
}
.shipment-card--ok   { border-left-color: var(--primary); }
.shipment-card--slow { border-left-color: #d97706; }       /* orange */
.shipment-card--late { border-left-color: #b94a3b; }       /* red   */
.shipment-card__head { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.shipment-card__title { font-size: 1rem; overflow-wrap: anywhere; }
.shipment-card__meta  { font-size: .85rem; color: var(--text); display: flex; flex-wrap: wrap; gap: .35rem; overflow-wrap: anywhere; }
.shipment-card__event { margin: 0; font-size: .9rem; line-height: 1.4; overflow-wrap: anywhere; }
.shipment-card__foot {
    display: flex; justify-content: space-between; align-items: center;
    gap: .5rem; flex-wrap: wrap;
    border-top: 1px solid var(--border-soft); padding-top: .75rem;
}
.shipment-card__carrier {
    display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
    font-size: .85rem;
}
.shipment-card__carrier code {
    font-size: .82rem; background: var(--surface-alt); padding: .12rem .4rem;
    border-radius: 4px; overflow-wrap: anywhere;
}
.shipment-card__actions { display: flex; gap: .4rem; flex-wrap: wrap; }
.shipment-card__actions .btn-sm { padding: .35rem .7rem; font-size: .85rem; }

/* ── 4-step progress bar ──
   Each step is a flex item with a dot above its label and a connector line
   to the next dot. The colour follows the parent .shipment-card--{tone} so
   age-urgency tints the whole timeline. */
.shipment-progress {
    list-style: none; padding: 0; margin: 0;
    display: flex; align-items: flex-start; gap: 0;
    counter-reset: ship-step;
}
.shipment-progress__step {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; align-items: center;
    text-align: center; position: relative;
    color: var(--muted); font-size: .72rem; line-height: 1.2;
}
.shipment-progress__dot {
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--surface-alt);
    border: 2px solid var(--border);
    margin-bottom: .4rem;
    flex-shrink: 0;
    z-index: 1;
}
/* Connector line between dots — drawn as a pseudo-element on every step
   except the last, anchored to the dot's vertical center. */
.shipment-progress__step:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 8px; /* (dot height 14 + border 2*2) / 2 ≈ 8px from the top of the dot */
    left: 50%;
    width: 100%;
    height: 2px;
    background: var(--border);
    z-index: 0;
}
.shipment-progress__label { padding: 0 .15rem; overflow-wrap: anywhere; }

/* Step states — done / current / todo. The card's --tone-color drives the
   final hue so an "ok" card stays green, a "late" card paints the whole
   bar red, etc. */
.shipment-card--ok   { --tone-color: var(--primary); }
.shipment-card--slow { --tone-color: #d97706; }
.shipment-card--late { --tone-color: #b94a3b; }

.shipment-progress__step--done .shipment-progress__dot,
.shipment-progress__step--current .shipment-progress__dot {
    background: var(--tone-color);
    border-color: var(--tone-color);
}
.shipment-progress__step--done::after { background: var(--tone-color); }
.shipment-progress__step--current .shipment-progress__label {
    color: var(--tone-color);
    font-weight: 600;
}
.shipment-progress__step--current .shipment-progress__dot {
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--tone-color) 20%, transparent);
}

/* Mobile: cards take full width, progress dots stay legible, labels
   shrink one step. */
@media (max-width: 480px) {
    .shipments-grid { grid-template-columns: 1fr; }
    .shipment-progress__label { font-size: .65rem; }
    .shipment-progress__dot { width: 12px; height: 12px; }
}

/* ============================================================================
 * UX tuning (audit admin 2026-05-30) — allègement du rythme + composants
 * de progressive disclosure. Ajouté en fin de feuille pour primer sur les
 * règles de base à spécificité égale. Voir docs/ux-audit-admin.md.
 * ========================================================================== */

/* L3 — Rythme vertical resserré (titres + cartes de stats). */
h1 { margin-bottom: 1rem; }
h2 { margin-bottom: .75rem; }
.dashboard-stat { padding: 1.1rem 1.25rem; }
.dashboard-stat__value { font-size: 1.6rem; }

/* C2 — Astérisque « champ requis ». */
.field-required { color: #b3261e; font-weight: 700; }

/* I1 / V2 / T2 — Sections repliables (progressive disclosure).
 * <details class="form-advanced-section"> avec un <summary> à deux lignes. */
.form-advanced-section {
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface-alt, rgba(0,0,0,.02));
    margin: 1rem 0;
}
.form-advanced-section > summary {
    cursor: pointer;
    list-style: none;
    padding: .7rem .9rem;
    display: flex;
    flex-direction: column;
    gap: .1rem;
    border-radius: 8px;
}
.form-advanced-section > summary::-webkit-details-marker { display: none; }
.form-advanced-section > summary::after {
    content: '▸';
    position: absolute;
    right: 1rem;
    color: var(--muted);
    transition: transform .15s ease;
}
.form-advanced-section[open] > summary::after { transform: rotate(90deg); }
.form-advanced-section > summary { position: relative; }
.form-advanced-section__title { font-weight: 600; font-size: .95rem; }
.form-advanced-section__hint { font-size: .8rem; }
.form-advanced-section__body { padding: 0 .9rem 1rem; }
.form-advanced-section--danger { border-color: rgba(179,38,30,.35); }
.form-advanced-section--danger .form-advanced-section__title { color: #b3261e; }

/* E1 — Variante « avancé » du séparateur de famille d'onglets. */
.settings-tabs__sep--advanced { opacity: .75; }

/* ──────────────────────────────────────────────────────────────────────────
   Dashboard — UX pass (D1-D7)
   D1 « À traiter » remonté en tête, pleine largeur, accent visuel.
   D3 graphique des visites repliable. D4 note moyenne condensée.
   D5 lignes de tableau cliquables (.js-row-link). D6 rythme vertical.
   ────────────────────────────────────────────────────────────────────────── */

/* D1 — call-out « À traiter » en tête de page */
.dashboard-todo {
    margin: 0 0 1.5rem;
    padding: 1rem 1.25rem;
    background: var(--surface, #fff);
    border: 1px solid var(--border-soft, #e6e2da);
    border-left: 4px solid var(--accent, #b8704f);
    border-radius: 10px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}
.dashboard-todo__title {
    margin: 0 0 .65rem;
    font-size: 1rem;
    font-weight: 700;
}
.dashboard-todo__list {
    margin: 0;
}
/* deux colonnes sur large écran quand plusieurs actions, une seule en mobile */
@media (min-width: 760px) {
    .dashboard-todo__list {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
        gap: .35rem .9rem;
    }
}
.dashboard-todo__hint {
    color: var(--muted, #8a8178);
    font-weight: 400;
    margin-left: .25rem;
}

/* D4 — note moyenne sur une ligne compacte */
.rating-inline {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem .75rem;
    margin: 0;
}
.rating-inline__stars { line-height: 1; }
.rating-inline__score { font-weight: 700; }
.rating-inline__count {
    color: var(--muted, #8a8178);
    font-size: .9rem;
}

/* D5 — lignes de tableau cliquables (sans onclick inline) */
tr.js-row-link { cursor: pointer; }
tr.js-row-link:hover { background: var(--row-hover, rgba(0, 0, 0, .03)); }
tr.js-row-link:focus-visible {
    outline: 2px solid var(--accent, #b8704f);
    outline-offset: -2px;
}

/* D2 — la carte « Depuis le lancement » a été fusionnée dans les KPI du haut.
   La rangée du bas peut donc n'avoir qu'une seule carte (« Pré-commandes ») :
   on la laisse occuper toute la largeur plutôt qu'un demi-vide à droite. */
.dashboard-bottom:has(> .dashboard-card:only-child) {
    grid-template-columns: 1fr;
}

/* Insights sur 3 colonnes : Top 3 · Note moyenne · Visites (côte à côte).
   align-items:start pour que la note (1 ligne) ne s'étire pas en grande
   carte vide ; le graphe garde sa hauteur naturelle à droite. */
.dashboard-insights.dashboard-insights--3col {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, .85fr) minmax(0, 1.45fr);
    align-items: start;
}
.dashboard-insights--3col > .dashboard-chart-card {
    width: 100%;
    min-width: 0;
}
@media (max-width: 1080px) {
    .dashboard-insights.dashboard-insights--3col { grid-template-columns: 1fr; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Ventes — passe UX (VL1-VL3, VP1-VP2, VD1-VD4, VX1)
   ────────────────────────────────────────────────────────────────────────── */

/* VL1 — graphe « Activité commerciale » repliable */
.sales-chart-details {
    margin: 0 0 1.25rem;
    border: 1px solid var(--border-soft, #e6e2da);
    border-radius: 10px;
    background: var(--surface, #fff);
}
.sales-chart-details > .sales-chart-card { margin: 0; border: 0; }
.sales-chart-details__summary {
    display: flex; align-items: baseline; gap: 1rem;
    padding: .8rem 1.1rem; cursor: pointer; font-weight: 600; list-style: none;
}
.sales-chart-details__summary::-webkit-details-marker { display: none; }
.sales-chart-details__summary::before {
    content: "▸"; color: var(--muted, #8a8178);
    transition: transform .15s ease; display: inline-block;
}
.sales-chart-details[open] .sales-chart-details__summary::before { transform: rotate(90deg); }
.sales-chart-details__hint { color: var(--muted, #8a8178); font-weight: 500; font-size: .9rem; }

/* VL2 — badges « statut effectif » (logistique fusionnée au paiement) */
.status-badge--needs-ship { background: #f6c544; color: #3d2c00; }
.status-badge--shipped    { background: #d9e6f2; color: #1f3a52; }
.status-badge--delivered  { background: #d8efe0; color: #14502f; }

/* VD1 — bouton d'action principale en tête de la fiche vente */
.sale-primary-cta {
    display: inline-flex; align-items: center; gap: .4rem;
    margin: 0 0 1.25rem;
}

/* VP1/VD2 + VD3 — blocs techniques / historiques repliés */
.tech-details, .trail-details {
    margin: .75rem 0 0;
    border-top: 1px solid var(--border-soft, #e6e2da);
    padding-top: .6rem;
}
.tech-details > summary, .trail-details > summary {
    cursor: pointer; color: var(--muted, #8a8178);
    font-size: .9rem; list-style: none;
}
.tech-details > summary::-webkit-details-marker,
.trail-details > summary::-webkit-details-marker { display: none; }
.tech-details > summary::before, .trail-details > summary::before {
    content: "▸ "; color: var(--muted, #8a8178);
}
.tech-details[open] > summary::before, .trail-details[open] > summary::before { content: "▾ "; }
.tech-details__list { list-style: none; margin: .6rem 0 0; padding: 0; }
.tech-details__list li {
    display: flex; justify-content: space-between; gap: 1rem;
    padding: .3rem 0; font-size: .85rem; border-top: 1px solid var(--border-soft, #efeae1);
}
.tech-details__list span { color: var(--muted, #8a8178); }
.tech-details__list code { font-size: .8rem; word-break: break-all; text-align: right; }

/* VX1/VP2 — APERÇU vente : masqué partout, affiché seulement dans le drawer */
[data-sale-apercu] { display: none; }
.sale-panel__body [data-sale-apercu] { display: block; padding: 1.25rem 1.4rem; }
.sale-apercu__head {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 1rem; flex-wrap: wrap;
}
.sale-apercu__eyebrow {
    margin: 0; text-transform: uppercase; letter-spacing: .06em;
    font-size: .72rem; color: var(--muted, #8a8178);
}
.sale-apercu__title { margin: .1rem 0 .4rem; font-size: 1.25rem; }
.sale-apercu__stats {
    list-style: none; margin: 1.1rem 0; padding: .9rem 0;
    border-top: 1px solid var(--border-soft, #e6e2da);
    border-bottom: 1px solid var(--border-soft, #e6e2da);
    display: grid; grid-template-columns: 1fr 1fr; gap: .75rem 1.25rem;
}
.sale-apercu__stats li { display: flex; flex-direction: column; min-width: 0; }
.sale-apercu__stats span {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted, #8a8178);
}
.sale-apercu__stats strong { font-size: .95rem; overflow-wrap: anywhere; }
.sale-apercu__lines { margin: 0; }
.sale-apercu__lines p { margin: .35rem 0; font-size: .92rem; }
.sale-apercu__todo {
    background: rgba(246, 197, 68, .15); border-radius: 6px;
    padding: .45rem .65rem; font-weight: 600;
}
.sale-apercu__hint { margin: 1rem 0 0; font-size: .82rem; color: var(--muted, #8a8178); font-style: italic; }

/* VD4 — cibles tactiles ≥ 44px sur mobile (page vente + drawer) */
@media (max-width: 720px) {
    [data-sale-detail] .btn,
    [data-sale-detail] button,
    [data-sale-detail] input:not([type=checkbox]):not([type=radio]),
    [data-sale-detail] select,
    .sale-panel__body .btn,
    .sale-panel__close { min-height: 44px; }
    .sale-apercu__head .btn { width: 100%; justify-content: center; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Avis + Messages — passe UX (MS1-MS3, AV1-AV3)
   ────────────────────────────────────────────────────────────────────────── */

/* MS1 — détail message dans le drawer (réutilise .sale-panel) */
[data-message-fullscreen] { display: none; }
.sale-panel__body [data-message-card] { padding: 1.25rem 1.4rem; }
.sale-panel__body [data-message-card] h1 { font-size: 1.3rem; margin-top: 0; }
.sale-panel__body [data-message-fullscreen] { display: inline-flex; }

/* AV3 — cibles tactiles ≥ 44px (boutons d'action Avis) sur mobile */
@media (max-width: 720px) {
    .reviews-action-btn,
    .reviews-table__expand,
    .reviews-bulk-bar .btn { min-height: 44px; }
    .reviews-table td { padding-top: .6rem; padding-bottom: .6rem; }
    .msg-row td { padding-top: .65rem; padding-bottom: .65rem; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Ambassadeurs — refonte UX (AB2-AB15)
   ────────────────────────────────────────────────────────────────────────── */

/* AB6 — barre de sous-onglets unifiée de l'univers Ambassadeurs. */
.amb-subnav {
    display: flex; gap: .25rem; flex-wrap: wrap;
    margin: 0 0 1.25rem;
    border-bottom: 1px solid var(--border);
}
.amb-subnav__tab {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .55rem .9rem;
    border-bottom: 2px solid transparent;
    color: var(--muted);
    font-size: .92rem; font-weight: 500;
    text-decoration: none;
    transition: color .12s, border-color .12s;
}
.amb-subnav__tab:hover { color: var(--text); }
.amb-subnav__tab.is-active {
    color: var(--primary);
    border-bottom-color: var(--accent);
    font-weight: 600;
}
.amb-subnav__count {
    display: inline-block; min-width: 1.25rem; padding: 0 .35rem;
    background: rgba(201, 162, 39, .18); color: #5c4500;
    border-radius: 999px; font-size: .72rem; font-weight: 700; text-align: center;
}

/* AB4 — bandeau d'état en tête : la prochaine action sous le nom. */
.ambassador-detail__next-action {
    margin: .5rem 0 0; font-size: .92rem;
    background: rgba(201, 162, 39, .1);
    border-left: 3px solid var(--accent, #c9a227);
    padding: .5rem .75rem; border-radius: 0 6px 6px 0;
}

/* AB5 — parcours d'intégration replié quand l'ambassadeur est actif. */
.ambassador-lifecycle__journey > summary {
    cursor: pointer; color: var(--muted); font-size: .9rem;
    padding: .35rem 0;
}
.ambassador-lifecycle__journey[open] > summary { margin-bottom: .5rem; }

/* AB3 — grille 4 KPI + bouton de versement sur la carte Solde + note réserve. */
.ambassador-detail__kpi-grid--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 900px) {
    .ambassador-detail__kpi-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ambassador-detail__kpi-cta {
    margin-top: .65rem; align-self: flex-start;
    font-size: .82rem; padding: .4rem .8rem;
}
.ambassador-detail__kpi-note {
    margin: .75rem 0 0; font-size: .88rem; color: var(--muted);
}

/* AB12 — aperçu ambassadeur : masqué partout, visible seulement dans le drawer.
   Réutilise le chrome .sale-apercu / .sale-panel des Ventes. */
[data-ambassador-apercu] { display: none; }
.sale-panel__body [data-ambassador-apercu] { display: block; padding: 1.25rem 1.4rem; }
.sale-panel__body [data-ambassador-apercu] .sale-apercu__head .btn { white-space: nowrap; }

/* AB14 — tableaux denses → cartes empilées en mobile (≤720px). Les <td>
   portent un data-label rendu en pseudo-élément côté étiquette. */
@media (max-width: 720px) {
    .ambassador-cards-mobile thead { display: none; }
    .ambassador-cards-mobile,
    .ambassador-cards-mobile tbody,
    .ambassador-cards-mobile tr,
    .ambassador-cards-mobile td { display: block; width: 100%; }
    .ambassador-cards-mobile tr {
        border: 1px solid var(--border);
        border-radius: 8px;
        padding: .5rem .75rem;
        margin-bottom: .75rem;
        background: var(--surface);
    }
    .ambassador-cards-mobile td {
        display: flex; justify-content: space-between; gap: 1rem;
        padding: .4rem 0; border: 0;
        text-align: right;
    }
    .ambassador-cards-mobile td::before {
        content: attr(data-label);
        font-weight: 600; color: var(--muted);
        text-align: left; flex: 0 0 auto;
    }
    .ambassador-cards-mobile td:empty,
    .ambassador-cards-mobile td[data-label=""]:empty { display: none; }
    /* Actions pleine largeur + cibles tactiles ≥ 44px. */
    .ambassador-cards-mobile td .btn,
    .ambassador-cards-mobile td button,
    .ambassador-cards-mobile td form { width: auto; }
    .ambassador-detail__codes-actions { width: 100%; }
    .ambassador-detail__codes-actions .btn,
    .ambassador-detail__codes-actions form,
    .ambassador-detail__codes-actions summary { width: 100%; min-height: 44px; }
}

/* === Self-hosted fonts (same files as public) === */
@font-face { font-family: 'Cinzel'; font-style: normal; font-weight: 400 700; font-display: swap; src: url('/assets/fonts/catalog/cinzel/cinzel-400-latin.woff2') format('woff2'); unicode-range: U+0000-00FF; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('/assets/fonts/catalog/inter/inter-400-latin.woff2') format('woff2'); unicode-range: U+0000-00FF; }

/* === Cross-document view transitions (2026) ===
 * Chrome 126+, Edge, Safari TP fade smoothly between admin pages — no
 * SPA framework needed. Browsers without support fall back to instant
 * navigation (no breakage). The header is excluded from the cross-fade
 * via `view-transition-name: admin-header` so it stays visually stable
 * while only the <main> content animates — eliminates the flicker the
 * user reported on title + nav. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: .22s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
.admin-header { view-transition-name: admin-header; }
.admin-main   { view-transition-name: admin-main; }
::view-transition-old(admin-header),
::view-transition-new(admin-header) { animation: none; }

/* === Reset === */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body.admin,
body.ambassador {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.6;
    font-size: 15px;
    min-height: 100vh;
}
*:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.btn:focus-visible { outline-offset: 4px; }
img { max-width: 100%; height: auto; display: block; }

/* === Typography === */
h1, h2, h3, h4 { font-family: 'Cinzel', Georgia, serif; color: var(--primary-dark); line-height: 1.2; font-weight: 600; }
h1 { font-size: 2rem; margin-bottom: 1.5rem; letter-spacing: -.005em; }
h1::after { content: ''; display: block; width: 50px; height: 3px; background: var(--accent); margin-top: .65rem; }
h2 { font-size: 1.4rem; margin-bottom: 1rem; }
h3 { font-size: 1.1rem; margin-bottom: .5rem; }
.admin code,
.ambassador code { font-family: 'SF Mono', Menlo, Consolas, monospace; font-size: .85em; background: var(--surface-alt); padding: 1px 6px; border-radius: 4px; color: var(--primary-dark); }
.admin-main a:not(.btn) { color: var(--primary); text-decoration: none; transition: color var(--transition); }
.admin-main a:not(.btn):hover { color: var(--accent); }
.ambassador-main a:not(.btn) { color: var(--primary); text-decoration: none; transition: color var(--transition); }
.ambassador-main a:not(.btn):hover { color: var(--accent); }

/* === Sortable + filterable + paginated list tables (admin-tables.js) === */

/* Horizontal-scroll container that admin-tables.js wraps around every
 * .admin-table. overflow-x:auto only shows a scrollbar when the table is
 * actually wider than the viewport (i.e. on mobile), so desktop is unaffected
 * while wide tables scroll sideways instead of overflowing or being clipped. */
.admin-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Filter row: lives inside <thead>, immediately UNDER the column-header
 * row, spanning all columns. Full-width input, counter on the right. */
.admin-table-bar-row td.admin-table-bar-cell {
    padding: .55rem .9rem !important;
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border);
}
.admin-table-bar {
    display: flex; align-items: center; gap: .75rem;
}
.admin-table-search {
    position: relative;
    flex: 1; min-width: 0;
    display: flex; align-items: center;
}
.admin-table-search svg {
    position: absolute; left: .85rem; top: 50%;
    transform: translateY(-50%);
    width: 14px; height: 14px;
    color: var(--muted); pointer-events: none;
}
.admin-table-filter {
    width: 100%;
    padding: .5rem .9rem .5rem 2.1rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .9rem;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.admin-table-filter::placeholder { color: var(--muted); }
.admin-table-filter:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
.admin-table-filter::-webkit-search-cancel-button { -webkit-appearance: none; }
.admin-table-counter {
    flex: 0 0 auto;
    font-size: .75rem; font-weight: 600;
    color: var(--primary-dark);
    background: rgba(201, 162, 39, .18);
    padding: .2rem .55rem;
    border-radius: 999px;
    white-space: nowrap;
}

/* Sortable column headers — chevron indicator on the right.
 *
 * The ⇅ glyph is drawn purely from CSS on every <th> that isn't opted-out
 * with data-no-sort, so it appears at first paint instead of waiting for
 * admin-tables.js to add the .admin-table-sortable class. The JS still
 * adds that class for hover/cursor behaviour and for the active-sort
 * styles (.admin-table-sorted-asc / -desc), but the indicator itself
 * renders without any JS round-trip. Avoids the visible flash of the
 * arrows appearing 1 s after the rest of the table.
 *
 * Scoped to thead > tr:first-child so the search-bar row injected by
 * _table-bar.php (which lives inside thead but has no THs) is unaffected. */
.admin-table:not([data-no-equip]) thead > tr:first-child th:not([data-no-sort]) {
    cursor: pointer; user-select: none; position: relative;
    padding-right: 1.5rem;
}
.admin-table:not([data-no-equip]) thead > tr:first-child th:not([data-no-sort])::after {
    content: '⇅'; position: absolute; right: .5rem; top: 50%;
    transform: translateY(-50%); opacity: .35; font-size: .75rem;
}
/* JS-added classes still drive hover background + active-sort glyph. */
.admin-table-sortable:hover { background: var(--surface-alt); }
.admin-table-sortable.admin-table-sorted-asc::after  { content: '▲'; opacity: 1; color: var(--accent); }
.admin-table-sortable.admin-table-sorted-desc::after { content: '▼'; opacity: 1; color: var(--accent); }

/* Pagination footer — flush against the bottom of the table card. */
.admin-table-pager {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
    padding: .65rem .9rem;
    background: var(--surface);
    border: 1px solid var(--border); border-top: none;
    border-radius: 0 0 var(--radius) var(--radius);
}
.admin-table-pager[hidden] { display: none; }
.admin-table:has(+ .admin-table-pager:not([hidden])) {
    border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.admin-table-pager__btn {
    min-width: 2rem; padding: .35rem .65rem;
    background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .82rem; color: var(--text);
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.admin-table-pager__btn:hover:not(:disabled) {
    background: var(--surface-alt); border-color: var(--accent);
}
.admin-table-pager__btn:disabled { opacity: .35; cursor: not-allowed; }
.admin-table-pager__btn[aria-current="page"] {
    background: var(--primary); border-color: var(--primary); color: var(--bg);
    font-weight: 600;
}
.admin-table-pager__ellipsis { color: var(--muted); padding: 0 .15rem; }

/* Right cluster: passive range info + interactive size selector,
 * styled as two distinct chips so the eye separates "state" from "control". */
.admin-table-pager__right {
    margin-left: auto;
    display: inline-flex; align-items: center; gap: .5rem;
}
.admin-table-pager__info {
    padding: .25rem .65rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 999px;
    font-size: .78rem; color: var(--muted);
    white-space: nowrap;
}
.admin-table-pager__size {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .15rem .55rem .15rem .7rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: .78rem; color: var(--text);
}
.admin-table-pager__size select {
    padding: .15rem .25rem;
    border: none;
    background: transparent; color: var(--text);
    font: inherit; font-size: .82rem; font-weight: 600;
    cursor: pointer;
}
.admin-table-pager__size:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px rgba(201, 162, 39, .25);
}
.admin-table-pager__size select:focus { outline: none; }

/* Clickable rows (any tbody <tr> tagged `data-row-href`).
 * The whole row navigates on click; subtle hover hint signals it. */
tr[data-row-href] { cursor: pointer; transition: background-color .12s ease; }
tr[data-row-href]:hover { background: var(--surface-alt); }
tr[data-row-href]:focus { outline: 2px solid var(--accent); outline-offset: -2px; }

/* === Book palette override (book-form Apparence pane) ===
 * Grid of color rows: round swatch (color picker) + label + hint +
 * source indicator ("Personnalisé" / "Hérité du thème"). The swatch is
 * a styled <input type="color"> so the native picker still opens. */
.palette-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: .65rem;
    margin-top: .25rem;
}
.palette-row {
    display: grid;
    grid-template-columns: 36px 1fr auto;
    align-items: center;
    gap: .85rem;
    padding: .65rem .85rem;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    transition: border-color var(--transition);
}
.palette-row:hover { border-color: var(--accent); }
.palette-row.is-custom { border-color: var(--primary); }
.palette-row__reset {
    width: 1.6rem; height: 1.6rem;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    font-size: .9rem;
    border-radius: 50%;
    cursor: pointer;
    padding: 0;
    margin-left: .25rem;
}
.palette-row__reset:hover { color: var(--primary); border-color: var(--primary); background: var(--surface-alt); }
.palette-row__reset[hidden] { display: none; }
/* Specificity boost via form scope: overrides the form-wide
 * `form input[type=color] { width:60px; height:36px }` rule. */
form .palette-row input[type=color].palette-row__swatch {
    width: 36px; height: 36px;
    padding: 0; border: 1px solid var(--border);
    border-radius: 50%;
    background: var(--surface-alt);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
}
.palette-row__swatch::-webkit-color-swatch-wrapper { padding: 0; border-radius: 50%; }
.palette-row__swatch::-webkit-color-swatch         { border: none; border-radius: 50%; }
.palette-row__swatch::-moz-color-swatch            { border: none; border-radius: 50%; }
.palette-row__text { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.palette-row__label {
    font-size: .9rem; font-weight: 600; color: var(--text);
    line-height: 1.2;
}
.palette-row__hint {
    font-size: .76rem; color: var(--muted);
    line-height: 1.3;
}
.palette-row__source {
    font-size: .7rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted);
    padding: .2rem .55rem;
    background: var(--surface-alt);
    border-radius: 999px;
    white-space: nowrap;
}
.palette-row.is-custom .palette-row__source {
    background: rgba(45, 80, 64, .14);
    color: var(--primary-dark);
}

/* === Genre tag-picker (GitHub-label-style) ===
 * One unified input box: selected genres as removable tags + a search input
 * inline. Suggestions popover below shows existing matches + a "Créer 'x'"
 * fallback when the typed text doesn't match any known genre. */
.genre-picker { position: relative; }
.genre-picker__selected {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
    min-height: 2.4rem;
    padding: .35rem .55rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: text;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.genre-picker__selected:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
.genre-tag {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .15rem .25rem .15rem .65rem;
    background: var(--primary);
    color: var(--bg);
    border-radius: 999px;
    font-size: .82rem; font-weight: 600;
    line-height: 1.4;
}
.genre-tag__remove {
    width: 18px; height: 18px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent;
    border: none; cursor: pointer;
    color: var(--bg);
    font-size: 1rem; line-height: 1;
    border-radius: 50%;
    transition: background var(--transition);
}
.genre-tag__remove:hover { background: rgba(248, 244, 236, .25); }
.genre-picker__input {
    flex: 1; min-width: 140px;
    padding: .25rem .35rem;
    border: none; outline: none; background: transparent;
    font: inherit; font-size: .85rem;
    color: var(--text);
}
.genre-picker__suggestions {
    position: absolute; top: calc(100% + .25rem); left: 0; right: 0;
    z-index: 5;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    max-height: 240px; overflow-y: auto;
    padding: .25rem;
}
.genre-suggestion {
    display: block; width: 100%; text-align: left;
    padding: .45rem .65rem;
    border: none; border-radius: var(--radius-sm);
    background: transparent;
    font: inherit; font-size: .85rem; color: var(--text);
    cursor: pointer;
}
.genre-suggestion:hover, .genre-suggestion:focus {
    background: var(--surface-alt); outline: none;
}
.genre-suggestion--create {
    border-top: 1px solid var(--border-soft);
    margin-top: .25rem; padding-top: .55rem;
    color: var(--accent);
}
.genre-suggestion--create strong { color: var(--primary-dark); }

/* === iOS-style toggle switch === */
.switch {
    display: inline-flex; align-items: center; gap: .5rem;
    cursor: pointer; user-select: none;
}
.switch input {
    position: absolute; opacity: 0; width: 0; height: 0;
    pointer-events: none;
}
.switch__slider {
    position: relative;
    display: inline-block; width: 38px; height: 22px;
    background: var(--border);
    border-radius: 999px;
    transition: background var(--transition);
}
.switch__slider::before {
    content: '';
    position: absolute; top: 2px; left: 2px;
    width: 18px; height: 18px;
    background: var(--surface);
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,.2);
    transition: transform var(--transition);
}
.switch input:checked + .switch__slider {
    background: var(--primary);
}
.switch input:checked + .switch__slider::before {
    transform: translateX(16px);
}
.switch input:focus-visible + .switch__slider {
    outline: 2px solid var(--accent); outline-offset: 2px;
}
.switch__label {
    font-size: .72rem; font-weight: 700;
    letter-spacing: .05em;
    color: var(--muted);
    min-width: 26px;
}
.switch input:checked ~ .switch__label { color: var(--primary-dark); }

/* === Promo row click affordance === */
.promo-row { cursor: pointer; transition: background var(--transition); }
.promo-row:hover { background: var(--surface-alt); }

/* === Promo modal === */
.promo-modal:not([open]) { display: none; }
.promo-modal {
    border: none; padding: 0;
    border-radius: var(--radius-lg);
    background: var(--surface); color: var(--text);
    width: min(640px, calc(100vw - 2rem));
    max-width: none;
    max-height: calc(100vh - 2rem);
    margin: auto;
    box-shadow: 0 28px 80px rgba(27, 58, 42, .35), 0 4px 12px rgba(0,0,0,.08);
    overflow: hidden;
}
.promo-modal[open] { display: flex; flex-direction: column; }
.promo-modal::backdrop {
    background: rgba(27, 58, 42, .55);
    backdrop-filter: blur(4px);
}
.promo-modal__inner {
    display: flex; flex-direction: column;
    overflow-y: auto;
}
.promo-modal__header {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 1.25rem 1.5rem 1rem;
    background: linear-gradient(180deg, var(--surface-alt) 0%, var(--surface) 100%);
    border-bottom: 1px solid var(--border);
}
.promo-modal__header h2 {
    margin: 0; font-size: 1.25rem; color: var(--primary-dark);
}
.promo-modal__header h2 code {
    background: transparent; color: var(--accent);
    font-family: 'SF Mono', monospace; font-size: 1.1rem;
}
.promo-modal__close {
    background: none; border: none;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.1rem; color: var(--muted);
    transition: color var(--transition), background var(--transition);
}
.promo-modal__close:hover { color: var(--primary-dark); background: var(--surface-alt); }
.promo-modal__body { padding: 0 1.5rem 1.5rem; }
.promo-modal__section { padding: 1.25rem 0; border-bottom: 1px solid var(--border-soft); }
.promo-modal__section:last-child { border-bottom: none; }
.promo-modal__section h3 { margin: 0 0 .5rem; font-size: 1rem; color: var(--primary-dark); }
.promo-modal__section--danger h3 { color: var(--danger); }
.promo-modal__hint { font-size: .82rem; color: var(--muted); margin: 0 0 .75rem; line-height: 1.5; }
.promo-modal__row { display: flex; gap: .75rem; align-items: end; flex-wrap: wrap; }
.promo-modal__row label { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: .35rem; font-size: .85rem; color: var(--muted); }
.promo-modal__row input[type=date] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; background: var(--surface);
}
.promo-modal__section--danger label {
    display: flex; flex-direction: column; gap: .35rem;
    font-size: .85rem; color: var(--muted); margin-bottom: .75rem;
}
.promo-modal__section--danger input[type=text] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-family: 'SF Mono', monospace;
}
.promo-modal__section--danger input[type=text]:focus {
    outline: none; border-color: var(--danger);
    box-shadow: 0 0 0 3px rgba(185, 28, 28, .15);
}

/* === Top-books-list cover thumbnails === */
.top-books-list__cover {
    width: 32px; height: 44px;
    border-radius: 3px;
    object-fit: cover;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    flex-shrink: 0;
}
.top-books-list__cover--empty {
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--muted);
}
.top-books-list__cover--empty svg { width: 18px; height: 18px; }

/* === Sales chart card (single dual-series chart on /admin/ventes) === */
.sales-chart-card {
    margin: 0 0 1.5rem; padding: 1.25rem 1.5rem;
    background: var(--surface);
    border: 1px solid var(--border-soft); border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.sales-chart__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    flex-wrap: wrap; gap: 1rem; margin-bottom: .9rem;
}
.sales-chart__heading { margin: 0; font-size: 1.05rem; color: var(--primary-dark); }
.sales-chart__subhead { margin: .15rem 0 0; font-size: .82rem; color: var(--muted); }
.sales-chart__periods { display: inline-flex; gap: .25rem; }
.sales-chart__periods button {
    padding: .35rem .75rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .82rem; font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.sales-chart__periods button:hover { background: var(--surface-alt); border-color: var(--accent); }
.sales-chart__periods button.is-active {
    background: var(--primary); border-color: var(--primary); color: var(--bg);
}
.sales-chart__legend {
    display: flex; gap: 1.5rem; margin-bottom: .5rem;
    flex-wrap: wrap;
}
.sales-chart__series {
    display: inline-flex; align-items: center; gap: .5rem;
    cursor: pointer;
    padding: .35rem .65rem;
    border-radius: var(--radius-sm);
    transition: background var(--transition);
}
.sales-chart__series:hover { background: var(--surface-alt); }
.sales-chart__series input { margin: 0; cursor: pointer; }
.sales-chart__series input:not(:checked) ~ .sales-chart__series-label,
.sales-chart__series input:not(:checked) ~ .sales-chart__series-total {
    text-decoration: line-through; opacity: .45;
}
.sales-chart__swatch {
    display: inline-block; width: 12px; height: 12px; border-radius: 3px;
}
.sales-chart__series--volume  .sales-chart__swatch { background: #2D5040; }
.sales-chart__series--revenue .sales-chart__swatch { background: #C9A227; }
.sales-chart__series-label { font-size: .85rem; color: var(--muted); }
.sales-chart__series-total {
    font-size: .95rem; color: var(--text); font-weight: 700;
}
.sales-chart__plot { position: relative; }
.sales-chart__svg {
    width: 100%; height: auto; max-height: 320px;
    display: block;
    cursor: crosshair;
}
.sales-chart__tooltip {
    position: absolute;
    z-index: 5;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .55rem .75rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12), 0 2px 6px rgba(0, 0, 0, .06);
    font-size: .82rem;
    line-height: 1.45;
    color: var(--text);
    min-width: 160px;
    pointer-events: none;
    transition: opacity .12s ease;
}
.sales-chart__tooltip[hidden] { display: none; }
.sales-chart__tooltip-date {
    font-weight: 600;
    margin-bottom: .35rem;
    color: var(--text);
    font-size: .8rem;
}
.sales-chart__tooltip-row {
    display: flex; align-items: center; gap: .5rem;
    padding: .15rem 0;
}
.sales-chart__tooltip-row strong {
    margin-left: auto;
    font-feature-settings: "tnum";
}
.sales-chart__tooltip-swatch {
    width: 10px; height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}
.sales-chart__tooltip-label { color: var(--muted); font-size: .78rem; }

/* === Export modal — centred via inset:auto + margin:auto on the dialog === */
.export-modal:not([open]) { display: none; }
.export-modal {
    border: none;
    border-radius: 14px;
    padding: 0;
    /* Wider so we can lay out Période + Statut side-by-side on desktop and
     * fit the field grid in 3 columns — eliminates most scrolling. */
    width: min(840px, calc(100vw - 2rem));
    max-width: none;
    max-height: min(85vh, 760px);
    background: var(--surface); color: var(--text);
    box-shadow: 0 30px 70px rgba(27, 58, 42, .4), 0 6px 14px rgba(0, 0, 0, .1);
    margin: auto;
    overflow: hidden;
}
.export-modal[open] { display: flex; flex-direction: column; }
.export-modal::backdrop { background: rgba(27, 58, 42, .55); backdrop-filter: blur(3px); }

/* Native form controls inherit the brand accent (primary green) instead of
 * the OS-default blue, scoped to the modal so it doesn't bleed elsewhere. */
.export-modal,
.export-modal input[type=checkbox],
.export-modal input[type=radio],
.export-modal input[type=date] {
    accent-color: var(--primary);
}

.export-modal__form {
    padding: 0;
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.export-modal__header {
    display: flex; align-items: center; justify-content: space-between;
    padding: .9rem 1.5rem;
    background: var(--primary);
    color: var(--surface);
    flex-shrink: 0;
}
.export-modal__header h2 {
    font-size: 1.05rem; margin: 0;
    color: inherit;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
}
.export-modal__close {
    background: none; border: none; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: inherit;
    padding: 0 .25rem;
    opacity: .85;
    transition: opacity .12s ease;
}
.export-modal__close:hover { opacity: 1; }

/* Body becomes a 2-col grid on desktop: Période + Statut share row 1, the
 * (full-width) Champs à exporter takes row 2. Mobile collapses to 1 col. */
.export-modal__body {
    flex: 1;
    overflow-y: auto;
    padding: 1rem 1.5rem;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem 1.25rem;
    align-items: start;
}
.export-modal__body > fieldset:nth-of-type(3) { grid-column: 1 / -1; }
@media (max-width: 720px) {
    .export-modal__body { grid-template-columns: 1fr; }
}

/* Override the global `form fieldset` chrome (border + cream bg + boxed
 * legend). The modal sections are simple typographic groupings instead. */
form.export-modal__form fieldset,
.export-modal fieldset {
    border: 0;
    border-radius: 0;
    background: transparent;
    padding: 0;
    margin: 0;
}
form.export-modal__form fieldset > legend,
.export-modal fieldset > legend {
    padding: 0;
    margin: 0 0 .55rem;
    background: transparent;
    border: 0;
    border-radius: 0;
    font-size: .68rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .14em;
}

.export-modal__row { display: flex; gap: .75rem; flex-wrap: wrap; }
.export-modal__row label {
    flex: 1; min-width: 130px;
    display: flex; flex-direction: column; gap: .25rem;
    font-size: .68rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .12em;
    font-weight: 600;
}
.export-modal__row input[type=date] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: 8px;
    font: inherit; background: var(--surface);
    color: var(--text);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
}
.export-modal__row input[type=date]:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(45, 80, 64, .12);
}
.export-modal__presets { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .65rem; }
.export-modal__presets .btn {
    padding: .3rem .7rem; font-size: .78rem;
    border-radius: 999px;
}

/* Status radios — stacked vertically inside the Statut column so the modal
 * stays compact, with custom-styled chrome (no boxy native radio). */
.export-modal fieldset > label {
    display: flex; align-items: center; gap: .55rem;
    margin: 0 0 .4rem;
    font-size: .9rem;
    cursor: pointer;
    line-height: 1.3;
}
.export-modal fieldset > label:last-child { margin-bottom: 0; }
.export-modal input[type=checkbox],
.export-modal input[type=radio] {
    width: 1.05rem; height: 1.05rem;
    margin: 0;
    flex-shrink: 0;
}

/* Champs à exporter — 3 cols on desktop to fit all 11 fields without scroll. */
.export-modal__fields {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .35rem 1rem;
}
.export-modal__fields > label {
    margin: 0;
    padding: .25rem 0;
}
@media (max-width: 720px) {
    .export-modal__fields { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
    .export-modal__fields { grid-template-columns: 1fr; }
}

.export-modal__footer {
    display: flex; justify-content: flex-end; gap: .6rem;
    padding: .85rem 1.5rem;
    background: var(--surface-alt, #f7f4ec);
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}
.export-modal__footer .btn-primary {
    min-height: 40px;
    padding: 0 1.25rem;
}

@media (max-width: 600px) {
    .export-modal { max-height: 92vh; border-radius: 12px 12px 0 0; }
}

/* === Status badges (pill display for enum-like status cells) ===
 * Wrap any status with <span class="status-badge status-badge--{slug}">.
 * Colors carry semantic meaning: green = active/positive, gold = pending/
 * in-progress, gray = neutral/archived, red = error/refunded. The slug
 * variants below cover every status enum used in the admin tables. */
.status-badge {
    display: inline-block;
    padding: .22rem .7rem;
    border-radius: 999px;
    font-size: .78rem; font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    background: rgba(0, 0, 0, .06);
    color: var(--muted);
}
/* Green — published, paid, approved, active, sent, read, visible */
.status-badge--published, .status-badge--paid, .status-badge--approved,
.status-badge--active, .status-badge--sent, .status-badge--read,
.status-badge--visible {
    background: rgba(4, 120, 87, .16);
    color: #065f46;
}
/* Gold — preorder, scheduled, pending, new (anticipation) */
.status-badge--preorder, .status-badge--scheduled, .status-badge--pending,
.status-badge--new {
    background: rgba(201, 162, 39, .25);
    color: #7a5e0f;
}
/* Slate-blue — draft (work in progress, not yet ready) */
.status-badge--draft {
    background: rgba(99, 102, 241, .14);
    color: #4338ca;
}
/* Amber — hidden (intentionally pulled but still there) */
.status-badge--hidden, .status-badge--invisible {
    background: rgba(245, 158, 11, .15);
    color: #b45309;
}
/* Gray — archived, unsubscribed, cancelled (cold / decommissioned) */
.status-badge--archived, .status-badge--unsubscribed, .status-badge--cancelled {
    background: rgba(0, 0, 0, .07);
    color: var(--muted);
}
/* Red — error / refunded / rejected / bounced / suspended */
.status-badge--refunded, .status-badge--rejected, .status-badge--bounced,
.status-badge--disputed, .status-badge--suspended {
    background: rgba(220, 38, 38, .12);
    color: #991b1b;
}
/* Generic colour aliases — useful when the badge label is dynamic and
 * doesn't map cleanly to a sematic state above. */
.status-badge--green { background: rgba(4, 120, 87, .16);  color: #065f46; }
.status-badge--gold  { background: rgba(201, 162, 39, .25); color: #7a5e0f; }
.status-badge--red   { background: rgba(220, 38, 38, .12); color: #991b1b; }
.status-badge--gray  { background: rgba(0, 0, 0, .07);     color: var(--muted); }

@media (max-width: 640px) {
    .admin-table-bar { flex-wrap: wrap; }
    .admin-table-counter { order: 2; margin-left: auto; }
    .admin-table-pager__info { width: 100%; margin-left: 0; text-align: center; }
}
.muted { color: var(--muted); }
small { color: var(--muted); }

/* === Header / nav === */
.admin-header {
    display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
    padding: 1rem 1.75rem;
    background: var(--primary);
    color: var(--bg);
    box-shadow: var(--shadow-sm);
    position: sticky; top: 0; z-index: 10;
}
.admin-header a { color: var(--bg); text-decoration: none; }
.admin-header .admin-brand {
    display: inline-flex;
    align-items: center;
    gap: .65rem;
    font-family: 'Cinzel', serif;
    font-size: 1.2rem; font-weight: 600;
    letter-spacing: .02em; padding-right: 1rem;
    border-right: 1px solid rgba(248, 244, 236, .15);
    margin-right: .25rem;
    color: var(--accent);
}
.admin-brand__mark {
    width: 32px; height: 32px;
    display: block;
    flex-shrink: 0;
}
.admin-brand__text { line-height: 1; }
.admin-header .admin-brand:hover { color: var(--bg); }
.admin-header .admin-brand:hover .admin-brand__mark { transform: scale(1.04); }
.admin-brand__mark { transition: transform .15s ease; }
@media (max-width: 600px) {
    .admin-brand__text { display: none; }
    .admin-header .admin-brand { padding-right: 0; border-right: 0; margin-right: 0; }
}
.admin-nav { flex: 1; display: flex; gap: .25rem; flex-wrap: wrap; }
.admin-nav a {
    padding: .5rem .9rem; border-radius: var(--radius-sm);
    font-size: .9rem; opacity: .85;
    transition: background var(--transition), opacity var(--transition), color var(--transition);
}
.admin-nav a:hover { opacity: 1; background: rgba(248, 244, 236, .08); color: var(--bg); }
/* Header badge — small pill next to a nav link when there's pending
 * work (unmoderated reviews, unread messages, ambassadors owed money). */
.admin-nav a { position: relative; }
.admin-nav__badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px;
    margin-left: .4rem;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--primary-dark);
    font-size: .68rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0;
    vertical-align: 1px;
}
.admin-nav a[aria-current="page"] {
    color: var(--primary-dark); background: var(--accent);
    opacity: 1; font-weight: 600;
}

/* === Mobile burger — ambassador portal header (layouts/ambassador.php) ===
 * Desktop: the burger is hidden and .amb-menu is display:contents, so the
 * nav + logout lay out as direct header flex children (desktop bar unchanged).
 * Mobile (≤768px, see the media query further down): the burger appears and
 * toggles the collapsed .amb-menu panel. */
.amb-menu { display: contents; }
.amb-burger {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 42px; height: 42px;
    padding: 0;
    border: 1px solid rgba(201, 162, 39, .55);
    border-radius: var(--radius-sm);
    background: transparent;
    cursor: pointer;
}
.amb-burger__bar {
    display: block;
    width: 20px; height: 2px;
    margin: 0 auto;
    background: var(--accent);
    transition: transform .2s ease, opacity .15s ease;
}
.amb-burger[aria-expanded="true"] .amb-burger__bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.amb-burger[aria-expanded="true"] .amb-burger__bar:nth-child(2) { opacity: 0; }
.amb-burger[aria-expanded="true"] .amb-burger__bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.admin-logout {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .45rem .9rem;
    border: 1px solid rgba(201, 162, 39, .55);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--accent) !important;
    font-size: .85rem; font-weight: 600;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.admin-logout svg { width: 16px; height: 16px; }
.admin-logout:hover {
    background: var(--accent);
    color: var(--primary-dark) !important;
    border-color: var(--accent);
}

/* === Header notification bell ==========================================
 * A bell button in the admin header with an unread-count badge; clicking
 * it drops a panel listing recent notifications. Each entry links to the
 * relevant admin page (NotificationsController marks it read en route). */
.admin-bell { position: relative; display: inline-flex; }
.admin-bell__btn {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px;
    border: 1px solid rgba(201, 162, 39, .55);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--accent);
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.admin-bell__btn svg { width: 18px; height: 18px; }
.admin-bell__btn:hover { background: var(--accent); color: var(--primary-dark); }
.admin-bell__badge {
    position: absolute; top: -6px; right: -6px;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--danger, #b94a48);
    color: #fff;
    font-size: .68rem; font-weight: 700; line-height: 1;
}
.admin-bell__panel {
    position: absolute; top: calc(100% + 8px); right: 0;
    width: 340px; max-width: calc(100vw - 2rem);
    background: var(--surface, #fff);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
    z-index: 50;
    overflow: hidden;
}
.admin-bell__panel[hidden] { display: none; }
.admin-bell__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: .5rem;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--border);
    font-size: .95rem;
}
.admin-bell__readall-form { margin: 0; }
.admin-bell__readall {
    border: 0; background: transparent;
    color: var(--primary);
    font-size: .8rem; cursor: pointer;
    padding: 0; text-decoration: underline;
}
.admin-bell__empty {
    margin: 0; padding: 1.25rem .9rem;
    color: var(--muted); font-size: .88rem; text-align: center;
}
.admin-bell__list {
    list-style: none; margin: 0; padding: 0;
    max-height: 380px; overflow-y: auto;
}
.admin-bell__item { border-bottom: 1px solid var(--border-soft, rgba(0, 0, 0, .06)); }
.admin-bell__item:last-child { border-bottom: 0; }
.admin-bell__item a {
    display: block;
    padding: .7rem .9rem;
    color: var(--text) !important;
    text-decoration: none;
    transition: background var(--transition);
}
.admin-bell__item a:hover { background: var(--surface-alt, rgba(0, 0, 0, .03)); }
.admin-bell__item.is-unread a { background: rgba(201, 162, 39, .1); }
.admin-bell__item.is-unread a:hover { background: rgba(201, 162, 39, .16); }
.admin-bell__item-title {
    display: block; font-weight: 600; font-size: .88rem;
    margin-bottom: .15rem;
}
.admin-bell__item-body {
    display: block; font-size: .82rem; color: var(--muted); line-height: 1.4;
}
.admin-bell__item-time {
    display: block; margin-top: .3rem;
    font-size: .72rem; color: var(--muted);
}
@media (max-width: 600px) {
    .admin-bell__panel {
        position: fixed; top: 64px; right: 1rem; left: 1rem; width: auto;
    }
}

/* === Main === */
.admin-main { max-width: 1280px; margin: 2.5rem auto; padding: 0 1.75rem; }
.admin-main > header {
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem;
    margin-bottom: 1.5rem;
}
.admin-main > header h1 { margin-bottom: 0; }

/* === Buttons === */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    padding: .55rem 1.1rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit; font-size: .9rem; font-weight: 500;
    cursor: pointer; text-decoration: none;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
}
.btn:hover { background: var(--surface-alt); border-color: var(--accent); transform: translateY(-1px); }
.btn-primary {
    background: var(--primary); color: var(--bg); border-color: var(--primary);
    font-weight: 600;
}
.btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: var(--bg); }
.btn-danger { background: var(--danger); color: white; border-color: var(--danger); font-weight: 600; }
.btn-danger:hover { background: #991b1b; border-color: #991b1b; color: white; }
.btn-secondary { background: var(--surface-alt); border-color: var(--border); }
.btn:disabled, .btn[disabled] {
    opacity: .5;
    cursor: not-allowed;
    transform: none;
    pointer-events: none;
}

/* === Sections / cards === */
.section {
    background: var(--surface);
    padding: 1.75rem;
    border-radius: var(--radius);
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
}
.section h2 {
    margin-top: 0; margin-bottom: 1.25rem;
    padding-bottom: .75rem; border-bottom: 1px solid var(--border-soft);
}

/* === KPI grid === */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
    margin-bottom: 2rem;
}
.kpi {
    display: block; text-decoration: none;
    background: var(--surface);
    padding: 1.5rem 1.75rem;
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    border-left: 4px solid var(--accent);
    transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
    cursor: pointer;
}
.kpi:hover {
    transform: translateY(-2px); box-shadow: var(--shadow);
    border-color: var(--accent);
}
.kpi-label {
    font-size: .8rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--muted); font-weight: 600;
    margin-bottom: .35rem;
}
.kpi-value {
    font-family: 'Cinzel', serif;
    font-size: 2.25rem; font-weight: 700; line-height: 1;
    color: var(--primary);
    margin: 0 0 .5rem;
}
.kpi-foot {
    margin: 0; font-size: .78rem; color: var(--accent); font-weight: 600;
}
.kpi:hover .kpi-foot { color: var(--primary-dark); }

/* === Tables === */
table {
    width: 100%; border-collapse: separate; border-spacing: 0;
    background: var(--surface);
    border-radius: var(--radius); overflow: hidden;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
}
table thead th {
    background: var(--primary);
    padding: .8rem 1rem;
    text-align: left;
    font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--bg); font-weight: 600;
    border-bottom: 1px solid var(--primary-dark);
}
/* Sortable header indicators in green-bg context: full-opacity cream
 * by default, gold when actively sorted. Targets the same paint-time
 * selector as the base rule above (no JS-added class needed for the
 * default chevron). */
table:not([data-no-equip]) thead > tr:first-child th:not([data-no-sort])::after { color: var(--bg); opacity: .55; }
table thead th.admin-table-sortable:hover { background: var(--primary-dark); }
table thead th.admin-table-sortable.admin-table-sorted-asc::after,
table thead th.admin-table-sortable.admin-table-sorted-desc::after { color: var(--accent); opacity: 1; }
table tbody td {
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--border-soft);
    font-size: .92rem;
    vertical-align: middle;
}
table tbody tr:last-child td { border-bottom: none; }
table tbody tr:hover { background: var(--surface-alt); }
table tbody tr td[colspan] { text-align: center; color: var(--muted); padding: 2rem; font-style: italic; }
.section table { box-shadow: none; border-radius: var(--radius-sm); }

/* === Forms === */
form label { display: block; margin: 1rem 0; font-size: .9rem; font-weight: 500; color: var(--text); }
/* The HTML5 `hidden` attribute must always win over the form-label display rule
 * above (same specificity, declaration order matters). */
form label[hidden] { display: none; }
form fieldset {
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    padding: 1.25rem 1.5rem 1rem;
    margin-bottom: 1.5rem;
    background: var(--surface-alt);
}
form fieldset > legend {
    padding: 0 .65rem;
    font-size: .85rem; font-weight: 600;
    color: var(--primary-dark);
    letter-spacing: .03em;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
}
form fieldset > label:first-of-type { margin-top: .5rem; }

form input[type=text], form input[type=email], form input[type=password],
form input[type=number], form input[type=date], form input[type=datetime-local],
form input[type=url], form input[type=search], form input[type=tel],
form select, form textarea {
    width: 100%; padding: .55rem .8rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .92rem;
    background: var(--surface); color: var(--text);
    transition: border-color var(--transition), box-shadow var(--transition);
}
form input:disabled, form select:disabled, form textarea:disabled {
    background: var(--surface-alt);
    color: var(--muted);
    border-color: var(--border-soft, var(--border));
    cursor: not-allowed;
    opacity: .8;
}
form input:focus, form select:focus, form textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
form textarea { resize: vertical; min-height: 100px; font-family: inherit; }

/* Selects: drop the native OS widget (its own chevron + box style clashed
 * with the site's inputs) and draw a discreet chevron in-house, so a
 * <select> reads exactly like a text field. */
form select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 2.25rem;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6' fill='none' stroke='%236f6f66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .85rem center;
    background-size: .72rem auto;
}
form input[type=checkbox], form input[type=radio] { width: auto; margin-right: .35rem; }
form input[type=color] { width: 60px; height: 36px; padding: 2px; cursor: pointer; }
form input[type=file] {
    width: 100%; padding: .5rem; border: 1px dashed var(--border);
    border-radius: var(--radius-sm); background: var(--surface);
    cursor: pointer; font-size: .9rem;
}
form input[type=file]:hover { border-color: var(--accent); }

form details {
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    padding: .85rem 1.25rem;
    margin-bottom: 1rem;
    transition: box-shadow var(--transition);
}
form details[open] { box-shadow: var(--shadow-sm); }
form details summary {
    cursor: pointer; font-weight: 600; color: var(--primary-dark);
    padding: .25rem 0;
}
form details summary:hover { color: var(--accent); }
form details > * + * { margin-top: .75rem; }

/* === Auth pages (login, totp-enroll, totp-recovery, totp-challenge) === */
.admin-login, .admin-totp, .admin-recovery {
    max-width: 460px; margin: 4rem auto;
    background: var(--surface);
    padding: 2.5rem;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--border-soft);
}
.admin-login h1, .admin-totp h1, .admin-recovery h1 { text-align: center; margin-bottom: 1.5rem; }
.admin-login h1::after, .admin-totp h1::after, .admin-recovery h1::after { margin-left: auto; margin-right: auto; }
.admin-totp p, .admin-recovery p { color: var(--muted); line-height: 1.7; }
.admin-totp img { margin: 1.5rem auto; border-radius: var(--radius); border: 1px solid var(--border); padding: .5rem; background: var(--surface); }
.admin-totp code {
    display: block; text-align: center;
    margin: 1rem 0; padding: 1rem;
    font-size: 1.1rem; letter-spacing: .15em;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--radius-sm); color: var(--primary-dark);
    word-break: break-all;
}
.admin-recovery ul {
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 1.25rem 2rem;
    list-style: none;
    columns: 2; column-gap: 2rem;
}
.admin-recovery li {
    padding: .35rem 0; font-family: 'SF Mono', Menlo, monospace;
    font-size: 1rem; letter-spacing: .05em; color: var(--primary-dark);
    break-inside: avoid;
}

/* === Flash messages === */
.flash {
    padding: .85rem 1.25rem; border-radius: var(--radius-sm);
    margin: 1rem 0; font-size: .9rem;
    border: 1px solid transparent;
}
.flash-error { background: var(--danger-soft); color: var(--danger); border-color: #fecaca; }
.flash-success { background: var(--success-soft); color: var(--success); border-color: #bbf7d0; }

/* === Mobile === */
@media (max-width: 768px) {
    .admin-header { padding: .75rem 1rem; }
    .admin-brand { padding-right: 0; border-right: none; margin-right: 0; }
    /* Nav drops to its own full-width row under the brand. `flex-basis`
       (not just `width`) is required: the base `.admin-nav{flex:1}` sets
       flex-basis:0, which would otherwise win and keep the nav inline. */
    .admin-nav {
        flex-basis: 100%;
        gap: .3rem;
        overflow-x: auto;
        flex-wrap: nowrap;
        padding-bottom: .25rem;
    }
    .admin-nav a { white-space: nowrap; padding: .4rem .75rem; font-size: .85rem; }

    /* Ambassador portal + admin: the nav collapses behind a burger button. */
    body.ambassador .amb-burger,
    body.admin .amb-burger { display: flex; margin-left: auto; }
    body.ambassador .amb-menu,
    body.admin .amb-menu {
        display: none;
        flex-basis: 100%;
        flex-direction: column;
        gap: .3rem;
        margin-top: .55rem;
    }
    body.ambassador .amb-menu.is-open,
    body.admin .amb-menu.is-open { display: flex; }
    body.ambassador .amb-menu .admin-nav,
    body.admin .amb-menu .admin-nav {
        flex: 0 0 auto;
        flex-direction: column;
        flex-wrap: nowrap;
        overflow: visible;
        gap: .15rem;
        width: 100%;
        padding-bottom: 0;
    }
    body.ambassador .amb-menu .admin-nav a,
    body.admin .amb-menu .admin-nav a {
        padding: .7rem .9rem;
        font-size: .95rem;
    }
    body.ambassador .amb-menu .admin-logout,
    body.admin .amb-menu .admin-logout {
        margin: .35rem 0 0;
        justify-content: center;
    }
    /* Admin-only header extras inside the collapsed menu (bell)
       — give them room and left-align like the nav links. */
    body.admin .amb-menu .admin-bell { margin: .35rem 0 0; }
    .admin-main { margin: 1.5rem auto; padding: 0 1rem; }
    .kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .kpi { padding: 1.25rem; }
    .kpi-value { font-size: 1.75rem; }
    table { font-size: .85rem; }
    table thead th, table tbody td { padding: .6rem .75rem; }
    .section { padding: 1.25rem; }
    .admin-main > header { flex-direction: column; align-items: stretch; }
    .admin-recovery ul { columns: 1; }

    /* === Ergonomie mobile globale (passe responsive admin) ================
     * Corrige d'un coup les constats transverses de l'audit par page :
     * cibles tactiles, zoom iOS, et chaînes insécables qui débordent. */
    body.admin .btn,
    body.admin .admin-logout { min-height: 44px; }
    /* iOS Safari zoome au focus dès qu'un champ est < 16px. */
    body.admin form input:not([type="checkbox"]):not([type="radio"]):not([type="color"]),
    body.admin form select,
    body.admin form textarea { font-size: 16px; }
    /* Emails, IDs Stripe, URLs, JSON… : casser au lieu de pousser la page. */
    body.admin .section a[href^="mailto:"],
    body.admin .section code,
    body.admin .section pre { overflow-wrap: anywhere; word-break: break-word; }
    /* Filet anti-débordement résiduel : absorbe les quelques px de slop (padding,
       éléments sr-only…). `clip` (≠ hidden) ne crée pas de conteneur de scroll,
       donc le scroll interne des .admin-table et le défilement vertical sont
       intacts. */
    body.admin .admin-main { overflow-x: clip; }

    /* Wide data tables (factures, codes, ventes…) scroll sideways INSIDE their
       .admin-table-wrap (added by admin-tables.js) instead of overflowing the
       page. The table stays display:table + width:100% so a narrow/empty table
       fills its column — no dead gutter on the right. The pager is inserted
       after the wrap, so it stays full-width and doesn't scroll with it. */
    body.ambassador .admin-table,
    body.admin .admin-table { width: 100%; }
    body.ambassador .admin-table th,
    body.ambassador .admin-table td,
    body.admin .admin-table th,
    body.admin .admin-table td { white-space: nowrap; }
    body.ambassador .ambassador-dashboard__month-table { table-layout: auto; }

    /* "Mes codes" embeds the share-link block (form content, not pure data) —
       a horizontal-scroll table mangles it. Stack it into cards instead,
       overriding the generic scroll rule above. */
    /* This table is restyled into stacked cards (block rows), so it must stay
       display:block — otherwise the default display:table would wrap the block
       rows in anonymous table boxes and break the card layout. */
    body.ambassador .ambassador-codes__table { display: block; overflow-x: visible; }
    body.ambassador .ambassador-codes__table thead { display: none; }
    body.ambassador .ambassador-codes__table tbody,
    body.ambassador .ambassador-codes__table tr,
    body.ambassador .ambassador-codes__table td { display: block; width: auto; }
    body.ambassador .ambassador-codes__table td { white-space: normal; }
    body.ambassador .ambassador-codes__table tr:not(.ambassador-codes__link-row) {
        border: 1px solid var(--border);
        border-radius: var(--radius, 8px);
        padding: .55rem .8rem;
        margin-bottom: .5rem;
    }
    body.ambassador .ambassador-codes__table tr:not(.ambassador-codes__link-row) td {
        padding: .15rem 0;
    }
    body.ambassador .ambassador-codes__table .ambassador-codes__link-row td { padding: 0; }
}

/* === Admin — très petits écrans (≤480px) : grilles KPI en 1 colonne ===== */
@media (max-width: 480px) {
    body.admin .kpi-grid,
    body.admin .ambassador-detail__kpi-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Dashboard widgets (added in migration 0013)
   ============================================================ */

/* ── Charts row ── */
.dashboard-charts {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    margin-bottom: 1.5rem;
}
@media (max-width: 720px) {
    .dashboard-charts { grid-template-columns: 1fr; }
}

.dashboard-chart-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    padding: 1.1rem 1.25rem 1rem;
    box-shadow: var(--shadow-sm);
    /* button reset */
    font: inherit;
    text-align: left;
    color: inherit;
    width: 100%;
    cursor: pointer;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.dashboard-chart-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0,0,0,.1);
    border-color: var(--accent);
}
.dashboard-chart-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.dashboard-chart-card__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .75rem;
}
.dashboard-chart-card__title {
    font-family: 'Cinzel', Georgia, serif;
    font-size: .95rem;
    color: var(--primary-dark);
    margin: 0;
}
.dashboard-chart-card__meta {
    font-size: .8rem;
    font-weight: 600;
    color: var(--muted);
    white-space: nowrap;
}
.dashboard-chart-card__subtitle {
    margin: .15rem 0 0;
    font-size: .77rem;
    color: var(--muted);
    font-style: italic;
    font-weight: 400;
}

/* ── Insights row ── */
.dashboard-insights {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}
@media (max-width: 900px) {
    .dashboard-insights { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 580px) {
    .dashboard-insights { grid-template-columns: 1fr; }
}

/* ── Generic dashboard card ── */
.dashboard-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    padding: 1.25rem;
    box-shadow: var(--shadow-sm);
    min-width: 0; /* grid item: allow shrinking so list rows ellipsize on mobile */
}
.dashboard-card h3 {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1rem;
    color: var(--primary);
    margin: 0 0 .85rem;
    padding-bottom: .55rem;
    border-bottom: 1px solid var(--border-soft);
}

/* ── Bottom row ── */
.dashboard-bottom {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    margin-bottom: 2rem;
    align-items: start;
}
.dashboard-bottom .alltime-card {
    display: flex; flex-direction: column;
    max-height: 220px;
}
.dashboard-bottom .alltime-card .alltime-card__metrics {
    flex: 1;
    align-content: center;
}
@media (max-width: 720px) {
    .dashboard-bottom { grid-template-columns: 1fr; }
}

/* ── Top books list ── */
.top-books-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.top-books-list__row {
    display: flex;
    align-items: center;
    gap: .75rem;
}
.top-books-list__rank {
    font-family: 'Cinzel', Georgia, serif;
    font-size: .8rem;
    font-weight: 700;
    color: var(--accent);
    min-width: 1.2rem;
    flex-shrink: 0;
}
.top-books-list__title {
    flex: 1;
    font-size: .9rem;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.top-books-list__title:hover { color: var(--accent); }
.top-books-list__stats {
    font-size: .78rem;
    color: var(--muted);
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── Rating display ── */
.rating-display {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    padding: .5rem 0;
    text-align: center;
}
.rating-display__stars {
    font-size: 1.85rem;
    line-height: 1;
    letter-spacing: .05em;
}
.star--full  { color: var(--accent); }
.star--half  { color: var(--accent); opacity: .65; }
.star--empty { color: var(--border); }
.rating-display__score {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--primary);
    margin: 0;
}
.rating-display__count {
    font-size: .82rem;
    color: var(--muted);
    margin: 0;
}
.rating-display__count a {
    color: var(--muted);
    text-decoration: none;
}
.rating-display__count a:hover { color: var(--accent); }

/* ── Action list ── */
.action-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .25rem;
}
.action-list li a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .55rem .75rem;
    border-radius: var(--radius-sm);
    background: rgba(201, 162, 39, .06);
    border: 1px solid rgba(201, 162, 39, .18);
    font-size: .88rem;
    color: var(--text);
    text-decoration: none;
    transition: background var(--transition), border-color var(--transition);
}
.action-list li a:hover {
    background: rgba(201, 162, 39, .14);
    border-color: var(--accent);
}
.action-list__arrow {
    color: var(--accent);
    font-weight: 700;
    flex-shrink: 0;
}

/* ── Preorders list ── */
.preorders-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.preorders-list__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}
.preorders-list__info {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    min-width: 0;
}
.preorders-list__info a {
    font-size: .9rem;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.preorders-list__info a:hover { color: var(--accent); }
.preorders-list__badge {
    font-size: .75rem;
    font-weight: 600;
    padding: .2rem .6rem;
    border-radius: var(--radius-pill);
    background: rgba(201, 162, 39, .18);
    color: #7a5e0f;
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── All-time card — inline summary stats (intentionally distinct from
 *    the top KPI grid: no card-in-card, no border-left, just icon +
 *    value + label in a row with thin gold dividers between metrics). ── */
.alltime-card__metrics {
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-wrap: wrap;
    align-items: center; gap: 0;
}
.alltime-card__metric {
    flex: 1; min-width: 160px;
    display: flex; align-items: center; gap: .75rem;
    padding: .25rem 1.25rem;
    border-right: 1px solid rgba(201, 162, 39, .35);
}
.alltime-card__metric:last-child { border-right: none; }
.alltime-card__metric svg {
    width: 28px; height: 28px;
    color: var(--accent);
    flex-shrink: 0;
}
.alltime-card__value {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.45rem; font-weight: 700; line-height: 1;
    color: var(--primary-dark);
    display: block;
}
.alltime-card__label {
    font-size: .72rem; letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted); font-weight: 600;
    margin-top: .15rem;
    display: block;
}
.alltime-card__text {
    display: flex; flex-direction: column;
    line-height: 1.1;
}
@media (max-width: 720px) {
    /* Drop the desktop height cap: with flex-wrap it made the 3 metrics wrap
       into 2 columns and align-content:center shoved them to the middle,
       leaving a big empty gutter. Let the card grow and stack cleanly. */
    .dashboard-bottom .alltime-card { max-height: none; }
    .dashboard-bottom .alltime-card .alltime-card__metrics {
        flex-direction: column; flex-wrap: nowrap;
        align-items: stretch; align-content: normal;
    }
    .alltime-card__metric { border-right: none; border-bottom: 1px solid rgba(201, 162, 39, .25); padding: .75rem 0; }
    .alltime-card__metric:last-child { border-bottom: none; }
}

/* ── Chart expand modal ─────────────────────────────────────────────────── */
.chart-modal:not([open]) { display: none; }
.chart-modal {
    border: none; padding: 0;
    border-radius: var(--radius-lg);
    background: var(--surface); color: var(--text);
    width: min(1100px, calc(100vw - 3rem));
    max-width: none;
    max-height: calc(100vh - 3rem);
    box-shadow: 0 28px 80px rgba(27, 58, 42, .35), 0 4px 12px rgba(0,0,0,.08);
    overflow: hidden;
    margin: auto; /* explicit centering — UA default but cemented */
}
.chart-modal[open] {
    display: flex; flex-direction: column;
}
.chart-modal::backdrop {
    background: rgba(27, 58, 42, .55);
    backdrop-filter: blur(4px);
}
.chart-modal__inner {
    display: flex; flex-direction: column;
    overflow-y: auto;
}

/* ── Header — title with gold accent underline, like dashboard h1 ───── */
.chart-modal__header {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 1.25rem 1.75rem 1rem;
    background: linear-gradient(180deg, var(--surface-alt) 0%, var(--surface) 100%);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.chart-modal__title {
    margin: 0;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.4rem;
    color: var(--primary-dark);
    letter-spacing: -.005em;
}
.chart-modal__title::after {
    content: ''; display: block;
    width: 36px; height: 2px;
    background: var(--accent);
    margin-top: .55rem;
}
.chart-modal__close {
    background: none; border: none;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.1rem; line-height: 1;
    color: var(--muted);
    transition: color var(--transition), background var(--transition);
}
.chart-modal__close:hover { color: var(--primary-dark); background: var(--surface-alt); }

/* ── Controls — chips group + date range ──────────────────────────────── */
.chart-modal__controls {
    display: flex; align-items: center;
    flex-wrap: wrap; gap: 1rem 1.5rem;
    padding: .9rem 1.75rem;
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.chart-modal__chips {
    display: inline-flex; gap: .25rem;
    background: var(--surface);
    padding: .25rem;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-soft);
}
.chart-modal__chip {
    padding: .4rem .85rem;
    border: none; border-radius: var(--radius-pill);
    background: transparent;
    color: var(--muted);
    font: inherit; font-size: .82rem; font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.chart-modal__chip:hover { color: var(--primary-dark); background: var(--surface-alt); }
.chart-modal__chip.is-active {
    background: var(--primary);
    color: var(--bg);
    box-shadow: 0 1px 3px rgba(45, 80, 64, .3);
}
.chart-modal__range {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}
.chart-modal__range-label {
    display: inline-flex; align-items: center; gap: .4rem;
    font-size: .8rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .05em;
}
.chart-modal__date-input {
    padding: .35rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .85rem;
    cursor: pointer;
}
.chart-modal__date-input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}

/* ── Chart plot wrapper hosts the SVG and the absolutely-positioned
 *    tooltip, mirroring the .sales-chart__plot pattern. ──────────────── */
.chart-modal__plot {
    position: relative;
    flex: 1 1 auto;
    background: var(--surface);
    padding: 1.5rem 1.75rem .5rem;
}
.chart-modal__svg {
    display: block;
    width: 100%;
    min-height: 280px; max-height: 460px;
    cursor: crosshair;
}
.chart-modal__tooltip {
    position: absolute;
    z-index: 5;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .55rem .75rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12), 0 2px 6px rgba(0, 0, 0, .06);
    font-size: .82rem;
    line-height: 1.45;
    color: var(--text);
    min-width: 160px;
    pointer-events: none;
    transition: opacity .12s ease;
}
.chart-modal__tooltip[hidden] { display: none; }
.chart-modal__tooltip-date {
    font-weight: 600;
    margin-bottom: .35rem;
    font-size: .8rem;
}
.chart-modal__tooltip-row {
    display: flex; align-items: center; gap: .5rem;
}
.chart-modal__tooltip-row strong {
    margin-left: auto;
    font-feature-settings: "tnum";
}
.chart-modal__tooltip-swatch {
    width: 10px; height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}
.chart-modal__tooltip-label { color: var(--muted); font-size: .78rem; }

/* ── Summary footer — gold-tinted info bar with the period span ─────── */
.chart-modal__summary {
    padding: .85rem 1.75rem 1rem;
    margin: 0;
    background: linear-gradient(0deg, var(--surface-alt) 0%, var(--surface) 100%);
    border-top: 1px solid var(--border);
    font-size: .85rem; color: var(--text);
    text-align: center;
    flex-shrink: 0;
}
@media (max-width: 600px) {
    .chart-modal {
        width: calc(100vw - 1rem);
        max-height: calc(100vh - 1rem);
        border-radius: var(--radius);
    }
    .chart-modal__header { padding: 1rem 1.1rem .85rem; }
    .chart-modal__title { font-size: 1.15rem; }
    .chart-modal__controls { padding: .75rem 1.1rem; gap: .75rem; }
    .chart-modal__plot { padding: 1rem 1.1rem 0; }
    .chart-modal__svg { min-height: 220px; }
    .chart-modal__summary { padding: .75rem 1.1rem 1rem; }
}

/* ============================================================
   Settings page — tabbed 2-column layout
   ============================================================ */

/* Two-column grid: fixed left rail + fluid right content area. */
.settings-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 1.5rem;
    align-items: start;
}
/* Grid items default to min-width:auto, which refuses to shrink below their
   content's min-content — on mobile (single 1fr column) that lets the form
   track balloon past the viewport. Force them to shrink so panes wrap. */
.settings-layout > nav,
.settings-layout > form { min-width: 0; }
/* <fieldset> carries an implicit `min-width: min-content` from the UA
   stylesheet that block-level `width` can't override — on mobile it refuses
   to shrink and forces horizontal overflow. Reset it everywhere in admin. */
body.admin fieldset { min-width: 0; }
/* Right column wrapper: lets the book form host extra standalone <form>
 * elements (file uploads, archive) inside the same column without
 * breaking the 2-col grid. Stacks them vertically. */
.settings-content {
    display: flex; flex-direction: column; gap: 1rem;
    min-width: 0;
}

/* ── Left rail ── */
.settings-tabs {
    position: sticky;
    top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}

/* ── Individual tab button ── */
.settings-tab {
    /* button reset */
    appearance: none;
    -webkit-appearance: none;
    border: none;
    background: none;
    margin: 0;
    font: inherit;
    /* layout */
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .6rem .85rem;
    border-radius: var(--radius-sm);
    width: 100%;
    text-align: left;
    font-size: .9rem;
    color: var(--text);
    cursor: pointer;
    transition: background .15s;
}
.settings-tab:hover { background: var(--surface-alt); }
.settings-tab.is-active {
    background: var(--primary);
    color: var(--bg);
}

/* ── Tab icon ── */
.settings-tab svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--tab-accent, var(--muted));
}
.settings-tab.is-active svg { color: var(--bg); }

/* ── Per-accent color variants (icon color when tab is NOT active) ── */
.settings-tab[data-accent="green"]  { --tab-accent: var(--primary); }
.settings-tab[data-accent="gray"]   { --tab-accent: var(--muted); }
.settings-tab[data-accent="gold"]   { --tab-accent: var(--accent); }
.settings-tab[data-accent="blue"]   { --tab-accent: #3b82f6; }
.settings-tab[data-accent="red"]    { --tab-accent: #ef4444; }
.settings-tab[data-accent="purple"] { --tab-accent: #8b5cf6; }
.settings-tab[data-accent="teal"]   { --tab-accent: #14b8a6; }
.settings-tab[data-accent="orange"] { --tab-accent: #f97316; }

/* ── Content panes ── */
.settings-pane {
    display: none;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    padding: 1.75rem;
    box-shadow: var(--shadow-sm);
}
.settings-pane.is-active { display: block; }

/* Spacing for direct children that are form controls / sections. */
.settings-pane > fieldset,
.settings-pane > .field,
.settings-pane > label {
    margin-bottom: 1.25rem;
}

/* ── Action buttons stack at the bottom of the rail ── */
.settings-actions {
    display: flex; flex-direction: column; gap: .5rem;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border-soft);
}
.settings-actions__btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: .5rem;
    width: 100%;
}
.settings-actions__btn svg { width: 16px; height: 16px; flex-shrink: 0; }
/* Disabled save button — applies to every settings-style form (book,
 * settings, promo) via the shared `.is-disabled` class plus the native
 * `:disabled` attribute on the legacy settings.php form. */
#settings-save:disabled,
.settings-actions__btn.is-disabled,
.settings-actions__btn[aria-disabled="true"] {
    background: var(--surface-alt) !important;
    color: var(--muted) !important;
    border-color: var(--border) !important;
    cursor: not-allowed;
    opacity: 1;
}
#settings-save:disabled:hover,
.settings-actions__btn.is-disabled:hover,
.settings-actions__btn[aria-disabled="true"]:hover {
    background: var(--surface-alt) !important;
    color: var(--muted) !important;
    transform: none;
}

/* ── Mobile: stack layout + horizontal scroll rail ──
   768px to match the admin burger-nav breakpoint (was 720, which left a
   721–768px dead zone where the burger showed but settings stayed 2-col). */
@media (max-width: 768px) {
    .settings-layout {
        grid-template-columns: 1fr;
    }
    .settings-tabs {
        position: static;
        flex-direction: row;
        flex-wrap: wrap;          /* tabs wrap to 2 rows — all visible, no hidden scroll */
        gap: .4rem;
        padding: .7rem .85rem;
    }
    .settings-tab {
        width: auto;              /* override the 100% from the vertical-rail base rule */
        flex: 0 1 auto;
        white-space: nowrap;
        padding: .5rem .8rem;
        font-size: .84rem;
    }
    /* Save button breaks onto its own full-width row below the tab strip. */
    .settings-actions {
        flex-basis: 100%;
        margin-top: .35rem;
        padding-top: .7rem;
    }
}

/* === Font picker: live preview card (book-form apparence pane) === */
.font-preview {
    padding: 1rem;
    border-radius: var(--radius);
    border: 1px solid var(--border-soft);
    background: var(--surface);
    margin-top: 1rem;
}
.font-preview__heading {
    font-family: var(--font-display-preview, inherit);
    font-size: 1.5rem;
    color: var(--primary-dark);
    margin-bottom: .5rem;
    line-height: 1.2;
}
.font-preview__body {
    font-family: var(--font-body-preview, inherit);
    font-size: 1rem;
    color: var(--text);
    line-height: 1.6;
    max-width: 65ch;
}

/* === Gallery card (Médias pane) — list of media + add form === */
.gallery-card {
    margin-top: 1.5rem;
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}
.gallery-card__header { margin-bottom: 1rem; }
.gallery-card__header h3 {
    margin: 0 0 .25rem;
    color: var(--primary-dark);
    font-size: 1rem;
}
.gallery-card__hint {
    margin: 0;
    font-size: .82rem;
    color: var(--muted);
}
.gallery-empty {
    margin: 0 0 1.25rem;
    padding: 1rem 1.25rem;
    background: var(--surface);
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    color: var(--muted);
    font-size: .9rem;
    text-align: center;
}
.gallery-grid {
    list-style: none; padding: 0; margin: 0 0 1.25rem;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: .85rem;
}
/* ── Gallery item card ── */
.gallery-item {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    overflow: visible;
    display: flex; flex-direction: column;
    position: relative;
    cursor: grab;
}
.gallery-item__thumb-wrap {
    position: relative;
    width: 100%; aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--surface-alt);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.gallery-item__thumb {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
/* Order badge — top-left, purely visual */
.gallery-item__order {
    position: absolute; top: .35rem; left: .35rem;
    background: rgba(27, 58, 42, .82);
    color: var(--bg);
    font-size: .68rem; font-weight: 700;
    padding: .1rem .4rem;
    border-radius: 999px;
    letter-spacing: .03em;
    pointer-events: none;
    z-index: 2;
}
/* Hover action bar — top-right */
.gallery-item__actions {
    position: absolute; top: .35rem; right: .35rem;
    display: flex; flex-direction: row; gap: .2rem;
    opacity: 0;
    transition: opacity .15s;
    z-index: 3;
}
.gallery-item:hover .gallery-item__actions { opacity: 1; }
/* Touch devices have no hover — the action bar would stay invisible, making
   delete/reorder unreachable on a phone. Always show it there, and grow the
   buttons toward a comfortable tap target. */
@media (hover: none) {
    .gallery-item__actions { opacity: 1; }
    .gallery-item__action { width: 36px; height: 36px; }
    .gallery-item__action svg { width: 16px; height: 16px; }
}
.gallery-item__action {
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,.55);
    color: #fff;
    border: none; border-radius: 4px;
    cursor: pointer;
    padding: 0;
    line-height: 1;
    flex-shrink: 0;
    transition: background .12s;
}
.gallery-item__action:hover { background: rgba(0,0,0,.75); }
.gallery-item__action svg { width: 14px; height: 14px; display: block; }
.gallery-item__drag-handle { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.gallery-item__drag-handle:active { cursor: grabbing; }
.gallery-item__drag-handle:active { cursor: grabbing; }
.gallery-item__delete-form { margin: 0; padding: 0; }
.gallery-item__delete-btn { background: rgba(180,30,30,.65); }
.gallery-item__delete-btn:hover { background: rgba(180,30,30,.9); }
/* Drag states */
.gallery-item.is-dragging {
    opacity: .35;
    cursor: grabbing;
}
.gallery-item.is-drop-target {
    outline: 2px dashed var(--accent);
    outline-offset: -4px;
}
/* Card body — compact caption strip */
.gallery-item__body {
    padding: .5rem .65rem;
    flex: 1;
}
.gallery-item__caption {
    margin: 0;
    font-size: .8rem; color: var(--text);
    line-height: 1.35;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
/* Slide-down edit panel */
.gallery-item__edit-panel {
    padding: .75rem;
    border-top: 1px solid var(--border-soft);
    background: var(--surface-alt);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.gallery-item__edit-panel[hidden] { display: none; }
.gallery-item__form {
    display: flex; flex-direction: column; gap: .6rem;
}
.gallery-item__form label {
    display: flex; flex-direction: column; gap: .2rem;
    font-size: .75rem; color: var(--muted);
}
.gallery-item__form input[type=text] {
    padding: .35rem .55rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .85rem;
    background: var(--surface);
}
.gallery-item__form-actions {
    display: flex; gap: .5rem;
    flex-wrap: wrap;
}
.gallery-item__form-actions .btn { padding: .3rem .65rem; font-size: .8rem; }
/* Add-media form */
.gallery-add-form {
    margin-top: 1rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
}
.gallery-add-form h4 {
    margin: 0 0 .85rem;
    color: var(--primary-dark);
    font-size: .92rem;
    font-weight: 600;
}
.gallery-add-form__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .75rem;
    margin-top: .85rem;
}
.gallery-add-form__row label {
    display: flex; flex-direction: column; gap: .25rem;
    font-size: .8rem; color: var(--muted);
}
.gallery-add-form__row input[type=text] {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .88rem;
    background: var(--surface);
}
.gallery-add-form__row input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}
.gallery-add-form__actions {
    display: flex; justify-content: flex-end;
    margin-top: .85rem;
}
@media (max-width: 640px) {
    .gallery-add-form__row { grid-template-columns: 1fr; }
}

/* === Cover upload card (Médias pane) — same look as EPUB card === */
.cover-upload-card {
    margin-top: 0;
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}
.cover-upload-card h3 {
    margin: 0 0 .85rem;
    color: var(--primary-dark);
    font-size: 1rem;
}
.cover-upload-card__current {
    display: flex; gap: 1rem; align-items: flex-start;
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-soft);
}
.cover-upload-card__thumb {
    width: 100px; aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: var(--radius-sm);
    box-shadow: 0 4px 12px rgba(0,0,0,.15);
    flex-shrink: 0;
}

/* === EPUB upload card (Synopsis pane) === */
.epub-upload-card {
    margin-top: 1.5rem;
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
}
.epub-upload-card h3 {
    margin: 0 0 .65rem;
    color: var(--primary-dark);
    font-size: 1rem;
}
.epub-upload-card__status {
    margin: 0 0 .85rem;
    font-size: .85rem;
    color: var(--muted);
}
.epub-upload-card__status code {
    background: var(--surface); border: 1px solid var(--border-soft);
    padding: 1px 6px; border-radius: 4px;
    color: var(--primary-dark);
}
.epub-upload-card__version {
    display: flex; flex-direction: column; gap: .35rem;
    margin-top: .85rem;
    font-size: .82rem; color: var(--muted);
}
.epub-upload-card__version input {
    padding: .5rem .65rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: .9rem;
    background: var(--surface);
}
.epub-upload-card__version input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}

/* === Médias placeholder (create page) === */
.medias-placeholder {
    text-align: center;
    padding: 2.5rem 1.5rem;
    background: var(--surface-alt);
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    color: var(--muted);
}
.medias-placeholder svg {
    width: 56px; height: 56px;
    color: var(--accent);
    margin: 0 auto .75rem;
    display: block;
    opacity: .85;
}
.medias-placeholder h3 {
    margin: 0 0 .75rem;
    color: var(--primary-dark);
    font-size: 1.05rem;
}
.medias-placeholder p { margin: 0 0 .5rem; line-height: 1.5; }
.medias-placeholder ul {
    text-align: left;
    max-width: 480px;
    margin: 1rem auto;
    padding-left: 1.25rem;
    line-height: 1.7;
}
.medias-placeholder ul strong { color: var(--text); }

/* === Live book-page preview (Apparence pane) ===
 * Mock book-detail card whose colors and fonts are driven by CSS variables
 * (--bp-*) that the JS sets from the palette pickers and font selects.
 * Defaults match the Livralyo global palette so the preview is meaningful
 * even when no per-book override is set. */
.book-preview {
    margin-top: 1.5rem;
    margin-bottom: 1.75rem;
}
.book-preview + fieldset {
    margin-top: 1.5rem;
}
.book-preview__header {
    display: flex; flex-direction: column; gap: .15rem;
    margin-bottom: .65rem;
}
.book-preview__caption {
    font-size: .78rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .06em; font-weight: 600;
}
.book-preview__hint {
    font-size: .8rem; color: var(--muted); font-style: italic;
}
.book-preview__frame {
    --bp-primary:      #2D5040;
    --bp-primary-dark: #1B3A2A;
    --bp-accent:       #C9A227;
    --bp-background:   #F8F4EC;
    --bp-surface:      #FFFFFF;
    --bp-text:         #1A1F18;
    --bp-muted:        #5C5C5C;
    --bp-border:       #E8DFC9;
    --bp-font-display: 'Cinzel', Georgia, serif;
    --bp-font-body:    'Lora', Georgia, serif;

    padding: 2rem 1.75rem;
    border-radius: var(--radius);
    border: 1px solid var(--bp-border);
    background: var(--bp-background);
    color: var(--bp-text);
    font-family: var(--bp-font-body);
    box-shadow: var(--shadow-sm);
}
.book-preview__hero {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: 1.75rem;
    align-items: start;
}
.book-preview__cover {
    width: 130px; aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: 4px;
    box-shadow: 0 6px 20px rgba(0,0,0,.18);
    background: var(--bp-surface);
}
.book-preview__cover--placeholder {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .65rem;
    color: var(--bp-muted);
    text-align: center;
    background:
        repeating-linear-gradient(45deg, transparent 0, transparent 6px, rgba(0,0,0,.03) 6px, rgba(0,0,0,.03) 12px),
        var(--bp-surface);
    border: 1px dashed var(--bp-border);
    box-shadow: none;
    font-size: .75rem; line-height: 1.3;
}
.book-preview__cover--placeholder svg { width: 32px; height: 32px; opacity: .55; }
.book-preview__info { min-width: 0; }
.book-preview__teaser {
    font-family: var(--bp-font-display);
    font-size: .8rem; font-weight: 700;
    color: var(--bp-accent);
    text-transform: uppercase; letter-spacing: .08em;
    margin: 0 0 .5rem;
}
.book-preview__title {
    font-family: var(--bp-font-display);
    font-size: 1.65rem; font-weight: 700; line-height: 1.1;
    color: var(--bp-primary);
    margin: 0 0 .35rem;
}
.book-preview__subtitle {
    color: var(--bp-muted);
    font-size: .92rem; font-style: italic;
    margin: 0 0 .55rem;
}
.book-preview__author {
    font-size: .85rem;
    color: var(--bp-text);
    margin: 0 0 1rem;
}
.book-preview__synopsis {
    font-size: .9rem; line-height: 1.6;
    margin: 0 0 1.25rem;
    padding-left: 1rem;
    border-left: 2px solid var(--bp-accent);
    color: var(--bp-text);
}
.book-preview__buy {
    background: var(--bp-accent);
    color: var(--bp-primary-dark);
    border: none;
    padding: .65rem 1.5rem;
    border-radius: 999px;
    font-family: var(--bp-font-body);
    font-weight: 700; font-size: .9rem;
    cursor: default;
    transition: opacity var(--transition);
}
.book-preview__buy:hover { opacity: .9; }
@media (max-width: 640px) {
    .book-preview__hero { grid-template-columns: 1fr; gap: 1rem; }
    .book-preview__cover { width: 100px; margin: 0 auto; }
}

/* === Custom font upload form — name input + dropzone + compact submit === */
.font-upload-form {
    padding: 1.25rem 1.5rem;
    background: var(--surface-alt);
    border-radius: var(--radius);
    border: 1px solid var(--border-soft);
    margin-top: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.font-upload-form__row { display: flex; flex-wrap: wrap; gap: .75rem; }
.font-upload-form__name { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: .35rem; }
.font-upload-form__name span { font-size: .85rem; color: var(--muted); }
.font-upload-form__name input {
    padding: .55rem .75rem;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); font: inherit; font-size: .9rem;
}
.font-upload-form__name input:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 162, 39, .18);
}

/* Drag-and-drop file dropzone — reused for font + EPUB uploads.
   `.font-dropzone` kept as alias for backward compatibility. */
.file-dropzone, .font-dropzone {
    position: relative;
    display: flex; align-items: center; gap: 1rem;
    padding: 1.25rem 1.5rem;
    background: var(--surface);
    border: 2px dashed var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.file-dropzone:hover, .file-dropzone.is-dragging,
.font-dropzone:hover, .font-dropzone.is-dragging {
    border-color: var(--accent); background: rgba(201, 162, 39, .06);
}
.file-dropzone.has-file,
.font-dropzone.has-file {
    border-color: var(--primary); background: rgba(45, 80, 64, .04);
    border-style: solid;
}
.file-dropzone__input,
.font-dropzone__input {
    position: absolute; inset: 0;
    opacity: 0; cursor: pointer;
    width: 100%; height: 100%;
}
form .file-dropzone .file-dropzone__input,
form .font-dropzone .font-dropzone__input {
    width: 100%; padding: 0; border: none; background: transparent;
}
.file-dropzone__icon,
.font-dropzone__icon {
    width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-alt);
    border-radius: 50%;
    color: var(--accent);
    flex-shrink: 0;
}
.file-dropzone.has-file .file-dropzone__icon,
.font-dropzone.has-file .font-dropzone__icon {
    background: rgba(45, 80, 64, .12); color: var(--primary);
}
.file-dropzone__icon svg,
.font-dropzone__icon svg { width: 22px; height: 22px; }
.file-dropzone__text,
.font-dropzone__text { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.file-dropzone__text strong,
.font-dropzone__text strong {
    color: var(--text); font-size: .95rem; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.file-dropzone__text span,
.font-dropzone__text span {
    color: var(--muted); font-size: .8rem;
}

.font-upload-form__actions { display: flex; justify-content: flex-end; }
.font-upload-form__actions .btn { padding: .5rem 1.25rem; }

.font-upload-form__success {
    background: var(--success-soft);
    color: var(--success);
    border: 1px solid #bbf7d0;
    padding: .85rem 1.25rem;
    border-radius: var(--radius-sm);
    font-size: .9rem;
}
.font-upload-form__error {
    background: var(--danger-soft);
    color: var(--danger);
    border: 1px solid #fecaca;
    padding: .85rem 1.25rem;
    border-radius: var(--radius-sm);
    font-size: .9rem;
}

/* === Cover crop tool (admin-cover-crop.js) ===
 * Replaces the cover dropzone after file selection with a draggable +
 * resizable 2:3 frame overlay. The frame, mask, handles and toolbar
 * are all injected by JS; these classes are never used before a file
 * is chosen, so there is no visual impact on the initial page render. */

/* Outer container — hidden by default, shown by JS */
.cover-crop-stage {
    display: flex;
    flex-direction: column;
    gap: .85rem;
}

/* Image wrapper — relative so frame + mask can be positioned inside */
.cover-crop-stage__img-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
    max-width: 100%;
    overflow: hidden;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    background: #000;
    cursor: default;
    user-select: none;
    -webkit-user-select: none;
}

/* The display image — fit to container width */
.cover-crop-stage__img {
    display: block;
    max-width: 100%;
    height: auto;
    pointer-events: none;
}

/* Full-cover semi-transparent mask — a "hole" is cut by clip-path in JS */
.cover-crop-mask {
    position: absolute;
    top: 0; left: 0;
    pointer-events: none;
    background: rgba(0, 0, 0, .52);
    /* clip-path is set dynamically by JS to cut a transparent rectangle
       matching the crop frame — creates the outside-dimming effect */
}

/* Draggable crop frame */
.cover-crop-frame {
    position: absolute;
    box-sizing: border-box;
    border: 2px solid rgba(255, 255, 255, .9);
    border-radius: 2px;
    cursor: move;
    touch-action: none;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Rule-of-thirds guide lines */
    background-image:
        linear-gradient(rgba(255,255,255,.18) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.18) 1px, transparent 1px);
    background-size: 33.33% 33.33%;
}

/* Centered "Recadrer" caption inside the frame */
.cover-crop-frame__label {
    color: rgba(255, 255, 255, .85);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-shadow: 0 1px 3px rgba(0,0,0,.7);
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
}

/* Corner resize handles — 10 × 10 px white squares */
.cover-crop-handle {
    position: absolute;
    width: 12px;
    height: 12px;
    background: #fff;
    border: 2px solid rgba(45, 80, 64, .7);
    border-radius: 2px;
    touch-action: none;
}
.cover-crop-handle--nw { top: -6px;  left: -6px;  cursor: nw-resize; }
.cover-crop-handle--ne { top: -6px;  right: -6px; cursor: ne-resize; }
.cover-crop-handle--sw { bottom: -6px; left: -6px;  cursor: sw-resize; }
.cover-crop-handle--se { bottom: -6px; right: -6px; cursor: se-resize; }

/* Toolbar below the image */
.cover-crop-toolbar {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
}

.cover-crop-toolbar__hint {
    flex: 1;
    font-size: .78rem;
    color: var(--muted);
    font-style: italic;
    min-width: 0;
}

.cover-crop-toolbar__reset,
.cover-crop-toolbar__change {
    font-size: .82rem;
    padding: .35rem .85rem;
    white-space: nowrap;
    flex-shrink: 0;
}

.cover-crop-toolbar__change {
    background: transparent;
    border-color: var(--border);
    color: var(--muted);
}
.cover-crop-toolbar__change:hover {
    border-color: var(--primary);
    color: var(--primary);
    background: transparent;
}

/* === Form draft banner (asks user to restore or discard) === */
.form-draft-banner {
    background: #fff7e0;
    border: 1px solid #d4a017;
    border-left: 4px solid #b88600;
    color: #8a5a00;
    padding: .65rem 1rem;
    border-radius: 6px;
    margin: 0 0 1rem;
    display: flex;
    flex-wrap: wrap;
    gap: .55rem;
    align-items: center;
    font-size: .92rem;
}
.form-draft-banner .muted { color: var(--muted); }

/* === Form success banner (top-of-form flash) === */
.form-success-banner {
    background: #ecf7ee;
    border: 1px solid #b7dec0;
    border-left: 4px solid #2d7a3a;
    color: #1f5532;
    padding: .65rem 1rem;
    border-radius: 6px;
    margin-bottom: 1rem;
    font-size: .92rem;
    font-weight: 500;
    animation: form-success-fade 6s forwards;
}
@keyframes form-success-fade {
    0%, 80%   { opacity: 1; max-height: 4rem; }
    100%      { opacity: 0; max-height: 0; padding: 0; margin: 0; border-width: 0; }
}

/* === Form error banner (top-of-form flash) === */
.form-error-banner {
    background: #fdecea;
    border: 1px solid #f5c2c2;
    border-left: 4px solid #c0392b;
    color: #7a1f1f;
    padding: .75rem 1rem;
    border-radius: 6px;
    margin-bottom: 1rem;
    font-size: .92rem;
    line-height: 1.45;
}
.form-error-banner em { font-style: normal; font-weight: 600; }

/* === Inline field hints === */
.field-hint {
    margin: -.4rem 0 .35rem;
    font-size: .82rem;
    color: var(--muted);
}
.field-hint--warning {
    color: #8a5a00;
    background: #fff7e0;
    border-left: 3px solid #d4a017;
    padding: .35rem .55rem;
    border-radius: 4px;
}

/* === Field-label row with inline info icon === */
.field-label-row {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}
.info-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    border-radius: 50%;
    cursor: pointer;
    transition: color .12s ease, background-color .12s ease;
}
.info-icon-btn:hover,
.info-icon-btn[aria-expanded="true"] {
    color: var(--primary);
    background: var(--surface-alt);
}
.info-icon-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* === Status info popover === */
.status-info-popover {
    position: relative;
    margin: .35rem 0 1rem;
    padding: 1rem 1rem .75rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 4px solid var(--accent);
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .06);
    max-width: 640px;
}
.status-info-popover[hidden] { display: none; }
.status-info-popover h4 {
    margin: 0 0 .55rem;
    font-size: .95rem;
    color: var(--primary);
}
.status-info-popover dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .45rem .85rem;
    margin: 0;
}
.status-info-popover dt { margin: 0; }
.status-info-popover dd {
    margin: 0;
    font-size: .88rem;
    line-height: 1.45;
    color: var(--text);
}
.status-info-popover__close {
    position: absolute;
    top: .25rem;
    right: .35rem;
    width: 1.6rem;
    height: 1.6rem;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    border-radius: 50%;
}
.status-info-popover__close:hover {
    color: var(--text);
    background: var(--surface-alt);
}

/* === Page builder ("Mise en page" tab) =================================== */
.page-builder {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, .9fr);
    gap: 1.5rem;
    margin-top: 1rem;
    align-items: start;
}
@media (max-width: 960px) {
    .page-builder { grid-template-columns: 1fr; }
}

.section-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.section-list__add {
    margin-top: .85rem;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

.section-item {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    gap: .75rem;
    align-items: center;
    padding: .65rem .8rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    transition: background-color .12s ease, border-color .12s ease, opacity .12s ease;
}
.section-item.is-dragging   { opacity: .4; }
.section-item.is-drop-target { box-shadow: 0 0 0 2px var(--accent) inset; }

.section-item--hidden { opacity: .5; background: var(--surface-alt); }
.section-item--hidden .section-item__title { text-decoration: line-through dotted; }

.section-item--empty { border-color: #d4a017; background: #fff8e6; }
.section-item--empty .section-item__title { color: var(--muted); }

.section-item--custom {
    border-left: 4px solid var(--accent);
}

/* Locked en-tête card — sits above the section list, cannot be dragged or hidden.
 * Visually distinct from regular section items so the author understands at a
 * glance that hero/cover/title/price are NOT part of the layout-driven list. */
.section-item--locked {
    background: linear-gradient(180deg, rgba(45, 80, 64, .04), rgba(45, 80, 64, 0)),
                var(--surface);
    border: 1px solid var(--primary);
    border-left-width: 4px;
    border-radius: 8px;
    margin-bottom: .85rem;
    padding: .65rem .8rem;
    display: grid;
    /* Same column shape as regular section rows so the actions column (palette
     * pastille) lines up on the right instead of wrapping to a new row. */
    grid-template-columns: auto auto 1fr auto;
    gap: .75rem;
    align-items: center;
    cursor: not-allowed;
}
/* Lock the cursor only on the non-interactive parts of the locked row;
 * the palette pastille and its panel must stay clickable. */
.section-item--locked .section-item__actions,
.section-item--locked .section-item__actions *,
.section-item--locked .section-item__palette,
.section-item--locked .section-item__palette * { cursor: auto; }
.section-item--locked .section-item__actions button { cursor: pointer; }
.section-item__handle--locked { color: var(--primary); }
.section-item--locked .section-item__icon { color: var(--primary); }
.section-item--locked .section-item__title { color: var(--primary); }
.section-item--locked .section-item__hint { color: var(--muted); font-style: italic; }

.section-item__handle {
    cursor: grab;
    color: var(--muted);
    display: inline-flex; align-items: center;
    /* Suppress native browser scroll when the user starts a drag from the
     * handle on touch devices (Pointer Events drag implementation). */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}
.section-item__handle:active { cursor: grabbing; }
.section-item__handle svg { width: 18px; height: 18px; pointer-events: none; }

.section-item__icon {
    color: var(--primary);
    display: inline-flex; align-items: center;
}
.section-item__icon svg { width: 20px; height: 20px; }

.section-item__main { min-width: 0; }
.section-item__title {
    font-weight: 600;
    color: var(--text);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.section-item__hint {
    font-size: .8rem;
    color: var(--muted);
    margin-top: .15rem;
}
.section-item__empty-tag {
    color: #8a5a00;
    font-weight: 500;
}

.section-item__actions {
    display: inline-flex;
    gap: .25rem;
}
.section-item__btn {
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--muted);
    cursor: pointer;
    padding: 0;
    transition: color .12s ease, background-color .12s ease, border-color .12s ease;
}
.section-item__btn:hover {
    color: var(--primary);
    border-color: var(--border);
    background: var(--surface-alt);
}
.section-item__btn[aria-pressed="false"] { color: #b94a48; }
.section-item__btn.is-active { color: var(--primary); border-color: var(--primary); }
.section-item__btn--danger:hover { color: #b94a48; border-color: #f5c2c2; background: #fdecea; }
.section-item__btn svg { width: 16px; height: 16px; }

/* Per-section palette panel — dropped below the section row when toggled.
 * The page-builder list lives OUTSIDE the main #book-form, so the
 * `form .palette-row input[type=color]` rules above do not apply here.
 * We re-declare swatch sizing locally so the picker renders as a 36px
 * circle instead of the browser's default oversized rectangle. */
.section-item__palette {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .65rem .75rem;
    margin-top: .35rem;
    border: 1px dashed var(--border);
    border-radius: 8px;
    background: var(--surface-alt, var(--surface));
}
.section-item__palette[hidden] { display: none; }
.section-item__palette .palette-row { padding: .35rem .5rem; }
.section-item__palette input[type=color].palette-row__swatch {
    width: 36px; height: 36px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: var(--surface-alt);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
}

/* === Page-builder preview pane (real iframe of the public page) ======== */
.page-builder__preview-col {
    position: sticky;
    top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}
.page-builder__preview-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .5rem;
}
.page-builder__preview-title {
    margin: 0;
    font-size: .9rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--muted);
}
.page-builder__preview-open {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .82rem;
    color: var(--primary);
    text-decoration: none;
    padding: .2rem .5rem;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: var(--surface);
}
.page-builder__preview-open:hover {
    background: var(--surface-alt);
    border-color: var(--primary);
}
.page-builder__preview-frame-wrap {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
    height: calc(100vh - 9rem);
    min-height: 480px;
}
.page-builder__preview-iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: #fff;
}
.page-builder__preview-loader {
    position: absolute;
    top: .65rem; left: .65rem;
    background: rgba(255, 255, 255, .92);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: .35rem .65rem;
    font-size: .82rem;
    color: var(--muted);
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    box-shadow: 0 4px 10px rgba(0, 0, 0, .08);
}
.page-builder__preview-loader[hidden] { display: none; }
.page-builder__preview-loader .spinner {
    width: 12px; height: 12px;
    border: 2px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: pb-spin .7s linear infinite;
}
@keyframes pb-spin { to { transform: rotate(360deg); } }

/* === Reviews bulk action bar =========================================== */
.reviews-bulk-bar {
    position: sticky;
    top: 0;
    z-index: 5;
    display: flex;
    gap: .65rem;
    align-items: center;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: .5rem .85rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-sm);
}
.reviews-bulk-bar__spacer { flex: 1; }
.reviews-row__check {
    width: 18px; height: 18px; cursor: pointer;
}

/* === Page-builder fullscreen preview modal ============================== */
/* The modal is JS-portalled to <body> at open time, so its stacking context
 * is the document root — guaranteed above the admin sticky header (z-index:10)
 * and the saved-button bar (z-index:5). z-index 9999 keeps headroom. */
.page-builder-fullscreen {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .82);
    z-index: 9999;
    display: flex;
    flex-direction: column;
    padding: 3.5rem 2rem 2rem;  /* top extra space so close button is reachable */
}
.page-builder-fullscreen[hidden] { display: none; }
.page-builder-fullscreen__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: #fff;
    margin-bottom: .65rem;
}
.page-builder-fullscreen__header h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 500;
    color: #fff;
}
.page-builder-fullscreen__close {
    /* Absolute position at top-right of the viewport so the X is ALWAYS
     * reachable, even if the header itself were ever clipped. */
    position: absolute;
    top: 1rem;
    right: 1rem;
    width: 2.4rem; height: 2.4rem;
    border: 1px solid rgba(255, 255, 255, .3);
    background: rgba(255, 255, 255, .08);
    color: #fff;
    font-size: 1.5rem;
    line-height: 1;
    border-radius: 50%;
    cursor: pointer;
    z-index: 1;
}
.page-builder-fullscreen__close:hover {
    background: rgba(255, 255, 255, .18);
}
.page-builder-fullscreen__body {
    flex: 1;
    background: #fff;
    border-radius: 8px;
    overflow: hidden;
    min-height: 0;
}
.page-builder-fullscreen__iframe {
    width: 100%; height: 100%;
    border: 0;
    display: block;
    background: #fff;
}

/* Section CRUD success toast */
.page-builder-toast {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 1100;
    background: #1f5532;
    color: #fff;
    padding: .55rem .9rem;
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
    font-size: .9rem;
    opacity: 0;
    transform: translateY(.5rem);
    transition: opacity .25s ease, transform .25s ease;
    pointer-events: none;
}
.page-builder-toast.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* === Custom-section editor modal ========================================= */
.section-modal {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 1rem;
}
.section-modal[hidden] { display: none; }
.section-modal__panel {
    background: var(--surface);
    border-radius: 12px;
    width: min(720px, 100%);
    max-height: calc(100vh - 2rem);
    overflow: auto;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
    padding: 1.25rem 1.5rem 1.5rem;
}
.section-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .75rem;
    border-bottom: 1px solid var(--border);
    padding-bottom: .55rem;
}
.section-modal__header h3 { margin: 0; font-size: 1.1rem; color: var(--primary); }
.section-modal__close {
    width: 2rem; height: 2rem;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: 1.5rem;
    line-height: 1;
    border-radius: 50%;
    cursor: pointer;
}
.section-modal__close:hover { background: var(--surface-alt); color: var(--text); }
.section-modal label { display: block; margin: .65rem 0; font-weight: 500; }
.section-modal label input,
.section-modal label textarea {
    width: 100%;
    margin-top: .3rem;
    font-family: inherit;
}
.section-modal label textarea {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .9rem;
    resize: vertical;
}
.section-modal__media-fieldset {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .65rem .85rem;
    margin: .85rem 0;
}
.section-modal__media-fieldset legend {
    padding: 0 .35rem;
    color: var(--primary);
    font-weight: 600;
}
.section-modal__media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: .5rem;
}
.section-modal__media-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .35rem;
    background: var(--surface-alt);
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
}
.section-modal__media-card.is-selected { border-color: var(--accent); background: var(--surface); }
.section-modal__media-card input[type="checkbox"] {
    position: absolute; top: .35rem; left: .35rem;
    width: 18px; height: 18px;
}
.section-modal__media-card img {
    width: 100%; height: 90px; object-fit: cover; border-radius: 4px;
}
.section-modal__media-card select { font-size: .8rem; }
.section-modal__actions {
    display: flex;
    justify-content: flex-end;
    gap: .5rem;
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--border);
}

/* === Sales list — clickable rows + slide-in detail panel ============= */
.sale-row { cursor: pointer; transition: background-color .12s ease; }
.sale-row:hover { background: var(--surface-alt, rgba(0, 0, 0, .03)); }
.sale-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* Wrapper covers the viewport so the backdrop + inner panel sit above the
 * page chrome. `hidden` hides it entirely until JS opens it. */
.sale-panel {
    position: fixed;
    inset: 0;
    z-index: 60;
    pointer-events: none;
}
.sale-panel:not([hidden]) { pointer-events: auto; }
.sale-panel__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(27, 58, 42, .35);
    opacity: 0;
    transition: opacity .22s ease;
    backdrop-filter: blur(2px);
}
.sale-panel.is-open .sale-panel__backdrop { opacity: 1; }
.sale-panel__inner {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: clamp(420px, 50vw, 720px);
    background: var(--surface);
    box-shadow: -16px 0 40px rgba(0, 0, 0, .18);
    transform: translateX(100%);
    transition: transform .25s cubic-bezier(.2, .7, .2, 1);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.sale-panel.is-open .sale-panel__inner { transform: translateX(0); }
.sale-panel__close {
    position: absolute;
    top: .85rem; right: .85rem;
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-alt, rgba(0, 0, 0, .04));
    border: 1px solid transparent;
    border-radius: 50%;
    font-size: 1.4rem; line-height: 1;
    color: var(--muted);
    cursor: pointer;
    z-index: 2;
    transition: color .12s ease, background-color .12s ease, border-color .12s ease;
}
.sale-panel__close:hover {
    color: var(--text);
    background: var(--surface);
    border-color: var(--border);
}
.sale-panel__body {
    flex: 1;
    overflow-y: auto;
    padding: 2rem 1.75rem 2rem;
}
/* The injected detail keeps its native h1/section styling but loses any
 * top margin so it sits right under the close button. The global
 * `h1::after` gold underline is decorative on full-page views; in the
 * panel it competes with the header chrome (close button + state badge),
 * so we hide it. */
.sale-panel__body [data-sale-detail] > h1:first-child,
.sale-panel__body [data-promo-detail] .promo-detail__head h1,
.sale-panel__body [data-book-detail] .book-detail__head h1 {
    margin-top: 0;
    padding-right: 3rem;
}
.sale-panel__body [data-sale-detail] h1::after,
.sale-panel__body [data-promo-detail] h1::after,
.sale-panel__body [data-book-detail] h1::after { display: none; }

.sale-panel__loader {
    display: flex; align-items: center; justify-content: center;
    padding: 3rem 0;
}
.sale-panel__loader .spinner {
    width: 24px; height: 24px;
    border: 3px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: pb-spin .7s linear infinite;
}

/* Lock body scroll when the panel is open so the page underneath doesn't
 * scroll behind the backdrop. */
body.has-sale-panel { overflow: hidden; }

@media (max-width: 720px) {
    .sale-panel__inner {
        width: 100%;
        box-shadow: none;
    }
    .sale-panel__body { padding: 1.25rem 1rem; }
}
@media (prefers-reduced-motion: reduce) {
    .sale-panel__inner { transition: none; }
    .sale-panel__backdrop { transition: none; }
}

/* === Sales detail — action cards (regen link / refund) ============== */
/* Used both inline on the full /admin/ventes/{id} page and inside the
 * slide-in panel from the list. Scope is on .sale-action so the styling
 * stays consistent in both contexts. */
.sale-action {
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 1.25rem 1.4rem;
    margin-bottom: 1rem;
    background: var(--surface);
    box-shadow: none;
}
.sale-action__head {
    display: flex;
    gap: .85rem;
    align-items: flex-start;
    margin-bottom: 1rem;
}
.sale-action__head svg {
    width: 22px; height: 22px;
    color: var(--primary);
    flex-shrink: 0;
    margin-top: .15rem;
}
.sale-action__head h2 {
    font-family: var(--font-body, system-ui), sans-serif;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
    margin: 0 0 .25rem;
    text-transform: none;
    letter-spacing: 0;
}
.sale-action__head p {
    margin: 0;
    color: var(--muted);
    font-size: .88rem;
    line-height: 1.45;
}
.sale-action__cta {
    height: 40px;
    padding: 0 1.1rem;
    font-size: .9rem;
    font-weight: 600;
    box-sizing: border-box;
}
/* Regen card: indent the standalone CTA so it lines up under the title
 * rather than under the icon. Indent = icon width (22px) + flex gap (.85rem). */
.sale-action--regen .sale-action__cta {
    margin-left: calc(22px + .85rem);
}

/* Refund card uses a 2-row grid: the label spans the input column on row 1,
 * and the input + the button share row 2. Putting them in the same row
 * (rather than aligning a single-line button to a 2-line label/input block)
 * gives a clean side-by-side alignment of the same-height controls. */
.sale-action__row {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
        "label   ."
        "input   button";
    gap: .35rem .75rem;
    margin-left: calc(22px + .85rem);
}
.sale-action__totp { display: contents; }
.sale-action__totp > span {
    grid-area: label;
    font-size: .7rem;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .12em;
}
.sale-action__totp > input {
    grid-area: input;
    height: 40px;
    box-sizing: border-box;
    padding: 0 .85rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font: inherit;
    font-feature-settings: "tnum";
    letter-spacing: .25em;
    background: var(--surface);
    color: var(--text);
    min-width: 0;
}
.sale-action__row > .btn { grid-area: button; align-self: stretch; }
.sale-action__totp > input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(45, 80, 64, .12);
}

/* Danger variant — red accent on the icon + cta, soft red background. */
.sale-action--danger {
    border-color: #f5c2c2;
    background: linear-gradient(180deg, #fff8f8, var(--surface));
}
.sale-action--danger .sale-action__head svg { color: #b94a48; }
.sale-action--danger .btn-danger {
    background: #b94a48;
    border-color: #b94a48;
    color: #fff;
}
.sale-action--danger .btn-danger:hover { background: #a13d3b; border-color: #a13d3b; }

/* Inside the panel: tighten spacing and drop the panel's own padding clash. */
.sale-panel__body .sale-action { margin-bottom: .85rem; }
.sale-panel__body .sale-action:last-child { margin-bottom: 0; }

/* === Promos list — badges, chips, toggle button ===================== */
.promo-row { cursor: pointer; transition: background-color .12s ease; }
.promo-row:hover { background: var(--surface-alt, rgba(0, 0, 0, .03)); }
.promo-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.ambassador-code-pill {
    display: inline-block;
    padding: .2rem .55rem;
    border-radius: 6px;
    background: rgba(45, 80, 64, .08);
    color: var(--primary-dark);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
    font-size: .85rem;
    font-weight: 600;
    letter-spacing: .04em;
}

.discount-badge {
    display: inline-block;
    padding: .2rem .55rem;
    border-radius: 999px;
    background: rgba(201, 162, 39, .15);
    color: #8a6a14;
    font-weight: 700;
    font-size: .82rem;
    font-feature-settings: "tnum";
}

.scope-chip, .target-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .2rem .55rem;
    border-radius: 999px;
    background: var(--surface-alt, rgba(0, 0, 0, .04));
    color: var(--muted);
    font-size: .78rem;
    font-weight: 500;
}
.scope-chip svg, .target-chip svg { width: 13px; height: 13px; flex-shrink: 0; }
.scope-chip--books { background: rgba(45, 80, 64, .08); color: var(--primary-dark); }
.target-chip--targeted { background: rgba(201, 162, 39, .14); color: #8a6a14; }

.promo-period { font-size: .85rem; color: var(--muted); }
.promo-period small { font-feature-settings: "tnum"; }

.usage-meter { display: flex; flex-direction: column; gap: .15rem; min-width: 80px; }
.usage-meter__count { font-size: .85rem; font-weight: 600; font-feature-settings: "tnum"; color: var(--text); }
.usage-meter__bar {
    display: block;
    height: 4px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .08);
    overflow: hidden;
}
.usage-meter__bar > span {
    display: block;
    height: 100%;
    background: var(--primary);
    transition: width .25s ease;
}
.usage-meter--warn .usage-meter__bar > span { background: #b94a48; }
.usage-meter--warn .usage-meter__count { color: #b94a48; }
.usage-meter--unlimited { display: inline-flex; align-items: baseline; gap: .35rem; }
.usage-meter--unlimited small { color: var(--muted); font-size: .75rem; }

.promo-state-cell {
    display: inline-grid;
    grid-template-columns: 100px auto;
    align-items: center;
    gap: .55rem;
}

.code-state-badge {
    display: inline-block;
    padding: .22rem .65rem;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    line-height: 1.4;
    white-space: nowrap;
    /* Centred inside the fixed-width grid cell so the ON/OFF toggle column
     * to the right lines up across rows regardless of label length. */
    text-align: center;
    justify-self: stretch;
    box-sizing: border-box;
}
.code-state-badge--active    { background: rgba(45, 110, 70, .15);  color: #1f6e3f; }
.code-state-badge--inactive  { background: rgba(0, 0, 0, .06);      color: var(--muted); }
.code-state-badge--expired   { background: rgba(185, 74, 72, .14);  color: #b94a48; }
.code-state-badge--scheduled { background: rgba(201, 162, 39, .18); color: #8a6a14; }
.code-state-badge--archived  { background: rgba(0, 0, 0, .12);      color: #555; }
/* Archived rows are dimmed but kept clickable so the admin can review the
 * historical detail. The discount/scope chips inside reuse their normal
 * colours so the row still reads cleanly. */
.promo-row--archived { opacity: .55; }
.promo-row--archived:hover { opacity: .75; }

.promo-toggle-btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: 0 .25rem;
    background: transparent;
    border: 0;
    cursor: pointer;
    font: inherit;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .08em;
    color: var(--muted);
    text-transform: uppercase;
}
.promo-toggle-btn__track {
    position: relative;
    width: 32px; height: 18px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .15);
    transition: background .15s ease;
}
.promo-toggle-btn__thumb {
    position: absolute;
    top: 2px; left: 2px;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--surface);
    transition: transform .15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
}
.promo-toggle-btn[aria-pressed="true"] .promo-toggle-btn__track { background: var(--primary); }
.promo-toggle-btn[aria-pressed="true"] .promo-toggle-btn__thumb { transform: translateX(14px); }
.promo-toggle-btn[aria-pressed="true"] { color: var(--primary); }
.promo-toggle-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }
.promo-toggle-btn:disabled { opacity: .5; cursor: progress; }

/* === Promo detail panel chrome ===================================== */
.promo-detail__head {
    display: flex; align-items: center; gap: .8rem;
    padding-right: 3rem;
    /* Breathing room before the first card so the title bar reads as a
     * standalone header rather than touching the table top. */
    margin-bottom: 1.25rem;
}
.promo-detail__head-meta {
    display: flex; align-items: center; gap: .65rem;
    flex-shrink: 0;
}
.promo-detail__head h1 {
    font-size: 1.25rem;
    margin: 0;
    flex: 1;
    display: flex; align-items: center; gap: .65rem; flex-wrap: wrap;
}
.promo-detail__code {
    font-family: var(--font-mono, ui-monospace, monospace);
    background: rgba(45, 80, 64, .1);
    color: var(--primary-dark);
    padding: .2rem .65rem;
    border-radius: 6px;
    font-size: 1rem;
}
.promo-detail__discount {
    background: rgba(201, 162, 39, .18);
    color: #8a6a14;
    padding: .2rem .65rem;
    border-radius: 999px;
    font-weight: 700;
    font-size: .9rem;
}
.promo-detail__book-list {
    margin: .4rem 0 0;
    padding: 0 0 0 1.1rem;
    color: var(--muted);
    font-size: .9rem;
}
.promo-detail__email-chip {
    display: inline-block;
    padding: .15rem .45rem;
    border-radius: 4px;
    background: rgba(0, 0, 0, .05);
    color: var(--muted);
    font-size: .8rem;
    margin: .1rem .25rem .1rem 0;
}
.promo-detail__bar {
    margin-top: .35rem;
    height: 6px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .08);
    overflow: hidden;
}
.promo-detail__bar-fill {
    height: 100%;
    background: var(--primary);
    transition: width .25s ease;
}
/* Detail-table card: no h2 (the panel header already provides context),
 * but keep balanced vertical padding so the first row doesn't sit flush
 * against the rounded top corner — that visual collision was reading as
 * "the row is overflowing the card". */
.section--detail-table { padding: .85rem 1.25rem; }
.section--detail-table .admin-detail-table { margin: 0; }
.admin-detail-table {
    width: 100%;
    border-collapse: collapse;
}
.admin-detail-table th {
    text-align: left;
    padding: .85rem 1rem .85rem 0;
    font-weight: 500;
    color: var(--muted);
    width: 38%;
    vertical-align: top;
    font-size: .85rem;
}
.admin-detail-table td {
    padding: .85rem 0;
    font-size: .92rem;
    vertical-align: top;
}
.admin-detail-table tr + tr th,
.admin-detail-table tr + tr td { border-top: 1px solid var(--border); }

/* The promo panel reuses the .sale-panel chrome — alias data-promo-panel
 * to the same visual styling without copying the rules. Already handled
 * because the markup uses .sale-panel class + a different data-* hook. */

/* Sales attributable to a promo, rendered inside the promo detail panel.
 * Compact rows, smaller font, no shadow — it's a sub-table inside an
 * already framed card. */
.promo-sales-table {
    margin: 1rem 0 0;
    box-shadow: none;
    font-size: .88rem;
}
.promo-sales-table th,
.promo-sales-table td { padding: .55rem .65rem; }
.promo-sales-table tbody tr + tr td { border-top: 1px solid var(--border-soft); }
.promo-sales-table small { font-size: .82rem; color: var(--muted); }

/* === Favicon upload widget (settings → identité) ====================
 * Two-thumbnail board: current favicon on the left, click-to-pick (or
 * post-crop preview) on the right. The actual <input type="file"> is
 * visually hidden — the dropzone label triggers it. The cropped image
 * is staged client-side and only persists when the main settings form
 * is submitted (the file ships as part of #settings-form). */
.favicon-upload {
    position: relative; /* contient l'input fichier sr-only (sinon il étend le scroll horizontal) */
    margin-top: 1rem;
    padding: 1.25rem 1.4rem 1.1rem;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    background: var(--surface-alt);
}
.favicon-upload__label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .14em;
    margin-bottom: 1rem;
}
.favicon-upload__flash { margin: 0 0 .85rem; }

.favicon-upload__board {
    display: flex; align-items: center; gap: 1.1rem;
    flex-wrap: wrap;
}
.favicon-upload__slot {
    display: flex; flex-direction: column; align-items: center; gap: .45rem;
    margin: 0;
}
.favicon-upload__slot figcaption {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--muted);
    font-weight: 600;
}
.favicon-upload__arrow {
    font-size: 1.4rem;
    color: var(--muted);
    line-height: 1;
    margin-bottom: 1.1rem; /* aligns with the thumb, ignoring caption row */
}
.favicon-upload__thumb {
    width: 72px; height: 72px;
    border-radius: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.favicon-upload__thumb img {
    max-width: 100%; max-height: 100%;
    width: 44px; height: 44px;
    object-fit: contain;
}
/* "Nouveau" thumb starts as a clickable dropzone with an upload icon.
 * Once a cropped preview is dropped in, .has-file removes the dashed
 * affordance and shows the cropped image like the "Actuel" slot. */
.favicon-upload__dropzone {
    display: flex; flex-direction: column; align-items: center; gap: .45rem;
    cursor: pointer;
    /* So the input which sits next to the dropzone in markup doesn't break
     * the column flow when keyboard-focused. */
}
.favicon-upload__thumb--new {
    border-style: dashed;
    border-color: var(--border);
    color: var(--muted);
    transition: border-color .15s, color .15s, background .15s;
}
.favicon-upload__thumb--new svg { width: 26px; height: 26px; }
.favicon-upload__dropzone:hover .favicon-upload__thumb--new,
.favicon-upload__dropzone:focus-within .favicon-upload__thumb--new {
    border-color: var(--primary);
    color: var(--primary);
    background: var(--surface);
}
.favicon-upload__thumb--new.has-file {
    border-style: solid;
    border-color: var(--accent);
    background: var(--surface);
}
.favicon-upload__thumb--new.has-file svg { display: none; }
.favicon-upload__dropzone-label {
    font-size: .85rem;
    color: var(--text);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-color: var(--border);
}
.favicon-upload__dropzone:hover .favicon-upload__dropzone-label {
    text-decoration-color: var(--primary);
    color: var(--primary);
}
.favicon-upload__input {
    /* Visually hidden but still focusable + ships as part of the form.
     * `display:none` would also work but that drops it from tab order. */
    position: absolute;
    left: 0; top: 0; /* pin to the (now relative) parent so it can't extend page scroll */
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.favicon-upload__hint {
    display: flex; align-items: flex-start; gap: .55rem;
    margin: 1rem 0 0;
    padding: .7rem .9rem;
    background: color-mix(in srgb, var(--accent) 14%, var(--surface) 86%);
    border-left: 3px solid var(--accent);
    border-radius: 6px;
    font-size: .88rem;
    color: var(--text);
}
.favicon-upload__hint svg {
    width: 16px; height: 16px;
    flex-shrink: 0;
    margin-top: 2px;
    color: var(--accent);
}
.favicon-upload__hint strong { color: var(--primary); }

.favicon-upload__formats {
    display: block;
    color: var(--muted);
    font-size: .8rem;
    margin-top: .85rem;
}

/* === Favicon crop modal (admin-favicon-crop.js) ====================== */
.favicon-crop-modal {
    border: 0;
    padding: 0;
    border-radius: 14px;
    width: min(560px, calc(100vw - 2rem));
    max-width: none;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 24px 60px rgba(27, 58, 42, .35), 0 4px 12px rgba(0, 0, 0, .08);
    margin: auto;
}
.favicon-crop-modal::backdrop { background: rgba(27, 58, 42, .55); backdrop-filter: blur(2px); }
.favicon-crop-modal__inner { display: flex; flex-direction: column; }
.favicon-crop-modal__header {
    display: flex; align-items: center; justify-content: space-between;
    padding: .9rem 1.25rem;
    background: var(--primary);
    color: var(--surface);
}
.favicon-crop-modal__header h2 {
    font-size: 1.05rem; margin: 0; color: inherit;
    font-weight: 600; text-transform: none; letter-spacing: 0;
}
.favicon-crop-modal__close {
    background: none; border: 0; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: inherit;
    padding: 0 .25rem; opacity: .85;
}
.favicon-crop-modal__close:hover { opacity: 1; }
.favicon-crop-modal__stage {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    background: repeating-conic-gradient(rgba(0,0,0,.04) 0% 25%, transparent 0% 50%) 50% / 16px 16px;
    overflow: hidden;
    user-select: none;
    touch-action: none;
}
.favicon-crop-modal__stage img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: contain;
    pointer-events: none;
    -webkit-user-drag: none;
}
.favicon-crop-modal__frame {
    position: absolute;
    box-sizing: border-box;
    border: 2px solid var(--accent);
    box-shadow: 0 0 0 9999px rgba(27, 58, 42, .55);
    cursor: move;
    touch-action: none;
}
.favicon-crop-modal__handle {
    position: absolute;
    right: -7px; bottom: -7px;
    width: 14px; height: 14px;
    background: var(--accent);
    border: 2px solid var(--surface);
    border-radius: 50%;
    cursor: nwse-resize;
}
.favicon-crop-modal__footer {
    display: flex; justify-content: flex-end; gap: .6rem;
    padding: .85rem 1.25rem;
    background: var(--surface-alt, #f7f4ec);
    border-top: 1px solid var(--border);
}

/* === Book detail panel (admin/livres/{id} → slide-in) =================
 * Layout for the standalone book-detail.php view (and its panel-injected
 * counterpart). Shares chrome with sales/promo panels (.sale-panel),
 * adds book-specific cover + stats UI. */
.book-detail__head {
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 1.25rem;
    align-items: start;
    margin-bottom: 1.75rem;
}
.book-detail__cover {
    width: 96px; aspect-ratio: 2 / 3;
    border-radius: 8px;
    overflow: hidden;
    background: var(--surface-alt);
    border: 1px solid var(--border);
}
.book-detail__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.book-detail__cover-placeholder {
    width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
    color: var(--muted);
}
.book-detail__cover-placeholder svg { width: 32px; height: 32px; }
.book-detail__head-body { min-width: 0; }
.book-detail__head-body h1 { margin: .35rem 0 .25rem; font-size: 1.6rem; }
.book-detail__subtitle {
    margin: 0 0 .85rem;
    color: var(--muted);
    font-size: .95rem;
    font-style: italic;
}
.book-detail__head-actions {
    display: flex; gap: .5rem; flex-wrap: wrap;
    margin-top: .85rem;
}
.book-detail__head-actions .btn {
    display: inline-flex; align-items: center; gap: .4rem;
}
.book-detail__head-actions .btn svg { width: 14px; height: 14px; }

.book-detail__synopsis {
    margin: 0;
    color: var(--text);
    line-height: 1.55;
    white-space: pre-wrap;
}

.book-detail__sales-summary {
    display: flex; gap: 1.25rem; flex-wrap: wrap;
    margin-bottom: 1rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border-radius: 8px;
    border: 1px solid var(--border-soft);
}
.book-detail__stat {
    display: flex; flex-direction: column; gap: .15rem;
    min-width: 0;
}
.book-detail__stat-value {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--primary);
    line-height: 1.2;
}
.book-detail__stat-label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--muted);
    font-weight: 600;
}

.book-sale-row { cursor: pointer; transition: background-color .12s ease; }
.book-sale-row:hover { background: var(--surface-alt, rgba(0,0,0,.03)); }
.book-sale-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* === Book detail — sales table fitted to the slide-in panel ============
 * The default .admin-table styles let columns size to content, which makes
 * the table overflow inside the panel (~520px wide). Lock columns with
 * table-layout:fixed and truncate the email cell so the panel never needs
 * a horizontal scrollbar. */
.book-detail__sales-table {
    table-layout: fixed;
    width: 100%;
}
.book-detail__col-date   { width: 7.5rem; }
.book-detail__col-amount { width: 5rem;   text-align: right; }
.book-detail__col-status { width: 6.5rem; }
.book-detail__sales-table th,
.book-detail__sales-table td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.book-detail__cell-email {
    direction: ltr;
}
.book-detail__sales-table .status-badge { font-size: .72rem; padding: .2rem .55rem; }

.book-detail__pager {
    display: flex; align-items: center; justify-content: space-between;
    gap: .5rem;
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--border-soft);
}
.book-detail__pager-btn {
    display: inline-flex; align-items: center;
    padding: .4rem .85rem;
    font-size: .85rem;
    color: var(--primary);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    text-decoration: none;
    transition: background .12s, border-color .12s;
}
.book-detail__pager-btn:hover {
    background: var(--surface-alt);
    border-color: var(--primary);
}
.book-detail__pager-btn[aria-disabled="true"] {
    opacity: .35;
    pointer-events: none;
}
.book-detail__pager-info {
    font-size: .82rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* === Book detail — sortable headers (server-side) =====================
 * The sales table opts out of admin-tables.js (data-no-equip) because the
 * dataset is paginated server-side; client-side sort would only reorder
 * the visible window. Headers are rendered as anchor links pointing at
 * the same URL with toggled sort/dir params; the panel JS intercepts
 * them via [data-book-detail-link] and re-fetches without a full nav. */
.book-detail__sales-table thead th {
    padding: 0;
}
.book-detail__sort-link {
    display: flex; align-items: center; justify-content: space-between;
    gap: .35rem;
    padding: .65rem .9rem;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    transition: background .12s;
}
.book-detail__sort-link:hover { background: var(--primary-dark); color: var(--bg); }
.book-detail__sort-arrow {
    font-size: .7rem;
    opacity: .55;
    color: inherit;
}
.book-detail__sales-table th.is-sorted .book-detail__sort-arrow {
    opacity: 1;
    color: var(--accent);
    font-weight: 700;
}

/* === Info popover next to settings labels =============================
 * Small "?" button anchored beside a field label. Reveals a contextual
 * explainer when clicked. Used e.g. for the commerce floor setting. */
.settings-label-with-info {
    position: relative;
    display: block;
}
.settings-label-with-info__text {
    display: inline-flex; align-items: center; gap: .35rem;
}
.settings-info-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    border-radius: 50%;
    transition: color .12s, background .12s;
}
.settings-info-btn:hover { color: var(--primary); background: var(--surface-alt); }
.settings-info-btn svg { width: 16px; height: 16px; }
.settings-info-popover {
    margin-top: .65rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border-left: 3px solid var(--accent);
    border-radius: 6px;
    font-size: .88rem;
    line-height: 1.5;
    color: var(--text);
}
.settings-info-popover h4 {
    margin: 0 0 .5rem;
    font-size: .82rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--primary);
}
.settings-info-popover p { margin: 0 0 .55rem; }
.settings-info-popover p:last-child { margin-bottom: 0; }
.settings-info-popover code {
    background: rgba(0,0,0,.06);
    padding: .05rem .35rem;
    border-radius: 3px;
    font-size: .85em;
}

/* === Ambassador detail panel (admin/ambassadeurs/{id}) ====================
 * Reuses the .sale-panel chrome; ambassador-specific layout below. */
.sale-panel__body [data-ambassador-detail] .ambassador-detail__head h1 {
    margin-top: 0;
    padding-right: 3rem;
}
.sale-panel__body [data-ambassador-detail] h1::after { display: none; }

.ambassador-detail__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
    padding-right: 3rem; /* room for the panel close button */
}
.ambassador-detail__head-body { min-width: 0; flex: 1; }
.ambassador-detail__head-body h1 { margin: .35rem 0 .25rem; font-size: 1.5rem; }
.ambassador-detail__email {
    margin: 0;
    color: var(--muted);
    font-size: .95rem;
}
.ambassador-detail__email a { color: inherit; text-decoration: underline dotted; }
.ambassador-detail__head-actions { flex-shrink: 0; }
.ambassador-detail__head-actions .btn {
    display: inline-flex; align-items: center; gap: .4rem;
}
.ambassador-detail__head-actions .btn svg { width: 14px; height: 14px; }

.ambassador-detail__commission-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .75rem;
}
.ambassador-detail__commission-card {
    display: flex; flex-direction: column; gap: .25rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
}
.ambassador-detail__commission-label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--muted);
    font-weight: 600;
}
.ambassador-detail__commission-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}
.ambassador-detail__commission-hint {
    font-size: .75rem;
    color: var(--muted);
    margin-top: .15rem;
}

.ambassador-detail__sales-table,
.ambassador-detail__codes-table {
    table-layout: fixed;
    width: 100%;
}
/* Sized for the panel viewport: date holds "DD/MM/YYYY HH:MM" + breathing
 * room, amount is right-aligned and tabular, status fits "Remboursé" with
 * margin from the panel edge. The Livre / Email columns flex on the rest. */
.ambassador-detail__col-date   { width: 9.75rem; }
.ambassador-detail__col-amount { width: 5.5rem; text-align: right; }
.ambassador-detail__col-status { width: 7rem; }

/* Ambassador dashboard — monthly history table: balanced column widths
 * (the month label no longer hogs the row; the three figure columns
 * share the remaining space evenly). */
.ambassador-dashboard__month-table { table-layout: fixed; }
.ambassador-dashboard__month-table th:first-child,
.ambassador-dashboard__month-table td:first-child { width: 28%; }
.ambassador-dashboard__col-num { width: 24%; text-align: right; }

/* === Ambassador lifecycle: stepper + next action + alerts === */
.ambassador-lifecycle { margin: 0 0 1.25rem; }
.ambassador-lifecycle__archived { color: var(--muted); font-style: italic; margin: 0 0 1rem; }
.ambassador-stepper {
    list-style: none; margin: 0 0 .9rem; padding: 0;
    display: flex; flex-wrap: wrap; gap: .25rem;
}
.ambassador-stepper__step {
    display: flex; align-items: center; gap: .45rem;
    flex: 1 1 auto; padding: .35rem .6rem; font-size: .82rem;
}
.ambassador-stepper__dot {
    flex: 0 0 auto; width: 1.5rem; height: 1.5rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: .8rem; font-weight: 700;
    background: var(--border); color: var(--surface);
}
.ambassador-stepper__label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ambassador-stepper__step.is-done    .ambassador-stepper__dot   { background: var(--primary); }
.ambassador-stepper__step.is-done    .ambassador-stepper__label { color: var(--muted); }
.ambassador-stepper__step.is-current .ambassador-stepper__dot   { background: var(--accent); }
.ambassador-stepper__step.is-current .ambassador-stepper__label { font-weight: 700; color: var(--text); }
.ambassador-stepper__step.is-error   .ambassador-stepper__dot   { background: #b3261e; }
.ambassador-stepper__step.is-error   .ambassador-stepper__label { font-weight: 700; color: #b3261e; }
.ambassador-stepper__step.is-todo    .ambassador-stepper__label { color: var(--muted); }
.ambassador-lifecycle__next {
    background: var(--surface-alt, rgba(0,0,0,.03));
    border: 1px solid var(--border); border-radius: var(--radius, 8px);
    padding: .6rem .85rem; margin: 0 0 .75rem;
    display: flex; flex-wrap: wrap; gap: .35rem 1.25rem; align-items: baseline;
}
.ambassador-lifecycle__next-action { margin: 0; font-size: .92rem; }
.ambassador-lifecycle__signature { margin: 0; font-size: .85rem; display: flex; gap: 1rem; flex-wrap: wrap; }
.ambassador-sig--done { color: var(--primary-dark, #2f6f4f); font-weight: 600; }
.ambassador-sig--wait { color: var(--muted); }
.ambassador-lifecycle__alert {
    margin: 0 0 .5rem; padding: .55rem .85rem;
    border-radius: var(--radius, 8px); font-size: .9rem; border: 1px solid;
}
.ambassador-lifecycle__alert--gold { background: rgba(201,162,39,.1); border-color: rgba(201,162,39,.4); }
.ambassador-lifecycle__alert--red  { background: rgba(179,38,30,.08); border-color: rgba(179,38,30,.35); color: #8a1f18; }

/* === Ambassador portal — onboarding progression === */
.ambassador-onboarding { margin: 1.5rem 0; }
.ambassador-onboarding__steps {
    list-style: none; margin: 0 0 1.5rem; padding: 0;
    display: flex; gap: .5rem; flex-wrap: wrap;
}
.ambassador-onboarding__step {
    flex: 1 1 140px;
    display: flex; flex-direction: column; align-items: center; gap: .45rem;
    text-align: center; padding: .5rem;
}
.ambassador-onboarding__dot {
    width: 2.25rem; height: 2.25rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-weight: 700;
    background: var(--border); color: var(--surface);
}
.ambassador-onboarding__label { font-size: .9rem; color: var(--muted); }
.ambassador-onboarding__step.is-done    .ambassador-onboarding__dot   { background: var(--primary); }
.ambassador-onboarding__step.is-current .ambassador-onboarding__dot   { background: var(--accent); }
.ambassador-onboarding__step.is-current .ambassador-onboarding__label { color: var(--text); font-weight: 700; }
.ambassador-onboarding__step.is-error   .ambassador-onboarding__dot   { background: #b3261e; }
.ambassador-onboarding__step.is-error   .ambassador-onboarding__label { color: #b3261e; font-weight: 700; }
.ambassador-onboarding__card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    padding: 1.5rem 1.75rem; text-align: center;
}
.ambassador-onboarding__card.is-error { border-color: rgba(179,38,30,.4); }
.ambassador-onboarding__card h2 { margin: 0 0 .5rem; }
.ambassador-onboarding__card p {
    margin: 0 auto 1rem; color: var(--muted); max-width: 540px;
}

/* === Portal info tooltip — tap/click the (i) to reveal a short note === */
.info-tip {
    position: relative;
    display: inline-block;
    vertical-align: middle;
    line-height: 1;       /* tight box: vertical-align then centres the actual
                             badge, not a line-box padded with empty space */
    margin-left: .35em;   /* breathing room from the preceding label text */
    top: -0.11em;         /* measured: cancels the ~1.5px x-height offset so the
                             badge sits on the text's centre */
}
.info-tip__btn {
    width: 1.1rem; height: 1.1rem; padding: 0;
    border: none; border-radius: 50%;
    background: var(--muted); color: var(--surface);
    font: 700 italic .72rem/1.1rem Georgia, serif;
    cursor: pointer;
}
.info-tip__btn:hover { background: var(--primary); }
.info-tip__bubble {
    display: none;
    position: absolute; left: 50%; transform: translateX(-50%);
    bottom: calc(100% + 9px);
    width: 250px; max-width: 76vw;
    background: #2a2a2a; color: #fff;
    font: 400 .8rem/1.45 inherit; font-style: normal; text-align: left;
    padding: .6rem .8rem; border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,.28);
    z-index: 60;
}
.info-tip.is-open .info-tip__bubble { display: block; }
.info-tip__bubble::after {
    content: ''; position: absolute; top: 100%; left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent; border-top-color: #2a2a2a;
}

/* === Portal "Comment suis-je payé ?" explainer === */
.ambassador-payinfo {
    margin: 1rem 0 0;
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    background: var(--surface);
}
.ambassador-payinfo > summary {
    cursor: pointer; padding: .8rem 1rem;
    font-weight: 600; color: var(--primary);
    list-style: none;
}
.ambassador-payinfo > summary::-webkit-details-marker { display: none; }
.ambassador-payinfo > summary::before { content: '💶 '; }
.ambassador-payinfo[open] > summary { border-bottom: 1px solid var(--border); }
.ambassador-payinfo__body { padding: .85rem 1.1rem; }
.ambassador-payinfo__body ol { margin: 0; padding-left: 1.2rem; }
.ambassador-payinfo__body li { margin: .4rem 0; line-height: 1.5; }

/* === Ambassador help page (workflow / glossary / FAQ) === */
.ambassador-help__flow { list-style: none; margin: 0; padding: 0; }
.ambassador-help__step {
    display: flex; align-items: flex-start; gap: .8rem;
    padding: .85rem 0;
    border-bottom: 1px solid var(--border);
}
.ambassador-help__step:last-child { border-bottom: none; }
.ambassador-help__step-num {
    flex: 0 0 auto;
    width: 1.7rem; height: 1.7rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--primary); color: var(--surface);
    font-weight: 700; font-size: .85rem;
}
.ambassador-help__step-icon { flex: 0 0 auto; font-size: 1.5rem; line-height: 1.5; }
.ambassador-help__step-body { display: flex; flex-direction: column; gap: .15rem; }
.ambassador-help__step-body strong { color: var(--text); }
.ambassador-help__step-body span { color: var(--muted); font-size: .92rem; line-height: 1.5; }
.ambassador-help__glossary { margin: 0; }
.ambassador-help__glossary dt { font-weight: 700; color: var(--primary); margin-top: .85rem; }
.ambassador-help__glossary dt:first-child { margin-top: 0; }
.ambassador-help__glossary dd {
    margin: .15rem 0 0; color: var(--muted); font-size: .92rem; line-height: 1.5;
}
.ambassador-help__faq { border-bottom: 1px solid var(--border); }
.ambassador-help__faq > summary {
    cursor: pointer; padding: .75rem 0; font-weight: 600; list-style: none;
    display: flex; justify-content: space-between; align-items: center; gap: 1rem;
}
.ambassador-help__faq > summary::-webkit-details-marker { display: none; }
.ambassador-help__faq > summary::after { content: '+'; color: var(--muted); font-size: 1.2rem; }
.ambassador-help__faq[open] > summary::after { content: '\2212'; }
.ambassador-help__faq > p {
    margin: 0 0 .85rem; color: var(--muted); font-size: .92rem; line-height: 1.55;
}
.ambassador-help__contact { text-align: center; }

/* === Ambassador profile completion bar + milestones === */
.profile-completion {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    padding: 1.1rem 1.25rem;
    margin: 0 0 1.5rem;
}
.profile-completion__head {
    display: flex; justify-content: space-between; align-items: baseline;
    flex-wrap: wrap; gap: .5rem; margin-bottom: .6rem;
}
.profile-completion__head h2 { margin: 0; font-size: 1.1rem; }
.profile-completion__count { color: var(--muted); font-size: .9rem; font-weight: 600; }
.profile-completion__bar {
    height: 8px; border-radius: 999px;
    background: var(--border); overflow: hidden; margin-bottom: 1rem;
}
.profile-completion__bar-fill {
    display: block; height: 100%;
    background: var(--primary); transition: width .3s ease;
}
.profile-completion__milestones { list-style: none; margin: 0; padding: 0; }
.profile-completion__milestone {
    display: flex; gap: .65rem; align-items: flex-start;
    padding: .55rem 0; border-top: 1px solid var(--border);
}
.profile-completion__milestone:first-child { border-top: none; }
.profile-completion__milestone-icon {
    flex: 0 0 auto; width: 1.5rem; height: 1.5rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: .85rem;
    background: var(--surface-alt, rgba(0,0,0,.05));
}
.profile-completion__milestone.is-done .profile-completion__milestone-icon {
    background: var(--primary); color: var(--surface); font-weight: 700;
}
.profile-completion__milestone-body { display: flex; flex-direction: column; gap: .1rem; }
.profile-completion__milestone-body strong { color: var(--text); }
.profile-completion__milestone.is-done .profile-completion__milestone-body strong { color: var(--muted); }
.profile-completion__milestone-desc { color: var(--muted); font-size: .88rem; line-height: 1.45; }
.profile-completion__milestone-missing {
    color: #8a1f18; font-size: .88rem; font-weight: 600; margin-top: .1rem;
}
.profile-completion__milestone.is-locked { opacity: .5; }
.profile-completion__milestone-next {
    color: var(--muted); font-size: .82rem; font-style: italic; margin-top: .1rem;
}

/* === Dashboard onboarding — "action requise" alert === */
.ambassador-onboarding__alert {
    margin-top: 1rem;
    background: rgba(201,162,39,.1);
    border: 1px solid rgba(201,162,39,.45);
    border-radius: var(--radius, 10px);
    padding: 1rem 1.15rem;
}
.ambassador-onboarding__alert strong { display: block; margin-bottom: .25rem; }
.ambassador-onboarding__alert p { margin: 0 0 .75rem; color: var(--text); line-height: 1.5; }
.ambassador-detail__col-book   { /* flex */ }
.ambassador-detail__sales-table th,
.ambassador-detail__sales-table td,
.ambassador-detail__codes-table th,
.ambassador-detail__codes-table td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Last column gets explicit right padding so the status badge doesn't
 * butt up against the table's outer border. */
.ambassador-detail__sales-table th:last-child,
.ambassador-detail__sales-table td:last-child,
.ambassador-detail__codes-table th:last-child,
.ambassador-detail__codes-table td:last-child {
    padding-right: 1rem;
}
.ambassador-detail__cell-truncate { direction: ltr; }

/* Codes table — 6 columns including an actions column (toggle / edit /
 * delete). It cannot fit a narrow ambassador panel, and the shared cell rule
 * above (overflow:hidden) was cropping the action buttons. Let this table
 * size to its content and scroll horizontally inside the panel instead. */
.ambassador-detail__codes-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.ambassador-detail__codes-table {
    table-layout: auto;
    min-width: 100%;
}
.ambassador-detail__codes-table th,
.ambassador-detail__codes-table td {
    overflow: visible;
    text-overflow: clip;
}
/* Action buttons stay on a single row; the column widens to fit them. */
.ambassador-detail__codes-actions {
    display: flex;
    gap: .4rem;
    align-items: flex-start;
    flex-wrap: nowrap;
}
/* Inline edit panel for a code, revealed by the <details> "Éditer" toggle. */
.ambassador-detail__code-edit > summary { cursor: pointer; }
.ambassador-detail__code-edit[open] > summary { margin-bottom: .5rem; }
.ambassador-detail__code-edit-form {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    min-width: 13rem;
    padding: .65rem .75rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-alt, rgba(0, 0, 0, .03));
}

.ambassador-sale-row,
.ambassador-detail__code-row {
    cursor: pointer;
    transition: background-color .12s ease;
}
.ambassador-sale-row:hover,
.ambassador-detail__code-row:hover {
    background: var(--surface-alt, rgba(0,0,0,.03));
}
.ambassador-sale-row:focus-visible,
.ambassador-detail__code-row:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

/* === Ambassador detail — tabbed layout =================================
 * The panel hosts 4 tabs (Synthèse / Informations / Commissions / Compta).
 * Tab nav is sticky-ish at the top of the panel body; only the active
 * pane is rendered visible to keep DOM cost low even with rate history
 * + payouts + invoices + documents loaded simultaneously. */
.ambassador-detail__tabs {
    display: flex;
    gap: .25rem;
    margin: 0 0 1.25rem;
    padding-bottom: .25rem;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
}
.ambassador-detail__tab {
    appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    padding: .5rem .9rem;
    font-size: .9rem;
    font-weight: 500;
    color: var(--muted);
    cursor: pointer;
    transition: color .12s, border-color .12s;
    white-space: nowrap;
}
.ambassador-detail__tab:hover { color: var(--text); }
.ambassador-detail__tab.is-active {
    color: var(--primary);
    border-bottom-color: var(--accent);
    font-weight: 600;
}
.ambassador-detail__pane { display: none; }
.ambassador-detail__pane.is-active { display: block; }

/* Inline alert banner (legal block missing, late payout, etc.). */
.ambassador-detail__alert {
    margin: 0 0 1.25rem;
    padding: .85rem 1rem;
    border-radius: 8px;
    font-size: .92rem;
}
.ambassador-detail__alert--warn {
    background: #fff8e6;
    border-left: 3px solid #d4a017;
    color: #5c4500;
}
.ambassador-detail__alert strong { color: inherit; }

/* KPI grid on the Synthèse tab — auto-fit so cards stay readable on
 * narrow panels. */
.ambassador-detail__kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .75rem;
    margin-bottom: 1.25rem;
}
.ambassador-detail__kpi {
    display: flex; flex-direction: column; gap: .15rem;
    padding: .85rem 1rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
}
.ambassador-detail__kpi--muted { opacity: .6; }
.ambassador-detail__kpi-label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--muted);
    font-weight: 600;
}
.ambassador-detail__kpi-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.ambassador-detail__kpi-hint {
    font-size: .75rem;
    color: var(--muted);
    margin-top: .15rem;
}

/* Promo chips on the Synthèse tab — at-a-glance overview of which codes
 * lead back to this ambassador. */
.ambassador-detail__code-chips {
    display: flex; flex-wrap: wrap; gap: .5rem;
}
.ambassador-detail__code-chip {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .35rem .65rem;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: .85rem;
    color: var(--text);
    text-decoration: none;
    transition: background .12s;
}
.ambassador-detail__code-chip:hover { background: var(--surface); border-color: var(--primary); }
.ambassador-detail__code-chip code {
    font-family: var(--font-mono, ui-monospace, monospace);
    background: rgba(45, 80, 64, .12);
    padding: .1rem .4rem;
    border-radius: 4px;
}

/* === Ambassador detail — payouts/documents/modal styling ================= */
.ambassador-detail__kpi--accent {
    background: color-mix(in srgb, var(--accent) 12%, var(--surface) 88%);
    border-color: var(--accent);
}
.ambassador-detail__kpi--accent .ambassador-detail__kpi-value { color: var(--primary-dark); }

.ambassador-detail__alert--danger {
    background: #fdecec;
    border-left: 3px solid var(--danger, #b94a48);
    color: #6c1f1f;
}

.ambassador-detail__row--voided {
    opacity: .55;
    text-decoration: line-through;
}
.ambassador-detail__row--voided td:first-child,
.ambassador-detail__row--voided td:last-child { text-decoration: none; }

.ambassador-detail__payouts-table th,
.ambassador-detail__payouts-table td {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Modal dialogs — used for payout recording + doc upload. Mirrors the
 * favicon-crop modal chrome (same project conventions). */
.ambassador-modal {
    border: 0;
    padding: 0;
    border-radius: 14px;
    width: min(640px, calc(100vw - 2rem));
    max-width: none;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 24px 60px rgba(27, 58, 42, .35), 0 4px 12px rgba(0, 0, 0, .08);
    margin: auto;
}
.ambassador-modal::backdrop { background: rgba(27, 58, 42, .55); backdrop-filter: blur(2px); }
.ambassador-modal__head {
    display: flex; align-items: center; justify-content: space-between;
    padding: .9rem 1.25rem;
    background: var(--primary);
    color: var(--surface);
}
.ambassador-modal__head h2 {
    font-size: 1.05rem; margin: 0; color: inherit; font-weight: 600;
    text-transform: none; letter-spacing: 0;
}
.ambassador-modal__close {
    background: none; border: 0; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: inherit;
    padding: 0 .25rem; opacity: .85;
}
.ambassador-modal__close:hover { opacity: 1; }
.ambassador-modal__body { padding: 1.25rem; }
.ambassador-modal__foot {
    display: flex; justify-content: flex-end; gap: .6rem;
    padding: .85rem 1.25rem;
    background: var(--surface-alt, #f7f4ec);
    border-top: 1px solid var(--border);
}
.ambassador-modal__balance {
    background: color-mix(in srgb, var(--accent) 12%, var(--surface) 88%);
    border-left: 3px solid var(--accent);
    padding: .55rem .85rem;
    border-radius: 6px;
    font-size: .92rem;
    margin-bottom: 1rem;
}

.btn-link {
    background: transparent; border: 0; padding: 0;
    cursor: pointer; text-decoration: underline;
}

/* Inline-aligned monospace pill — neutralises the `<code>` block padding
 * so that SIRET/IBAN values sit on the same baseline as the plain text
 * values in adjacent rows. The original `<code>` styling pushed the
 * cell content downward visually because of its background + padding. */
.detail-table .detail-mono {
    display: inline;
    background: rgba(45, 80, 64, .08);
    padding: .08em .4em;
    border-radius: 4px;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: .92em;
    /* Match the line-height of the surrounding text — without this the
     * baseline visually slips because the default <code> sets height. */
    line-height: inherit;
    vertical-align: baseline;
}

.ambassador-detail__proof-cell {
    display: inline-flex; align-items: center; gap: .5rem;
    white-space: nowrap;
}
.ambassador-detail__proof-btn {
    color: var(--primary);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.ambassador-detail__proof-btn:hover { color: var(--primary-dark); }

/* === Ambassador detail — commission rate timeline ========================
 * Vertical timeline showing the ambassador's rate changes over time. The
 * current slice (effective_to IS NULL) gets the accent treatment so the
 * "where we are now" is unmistakable. */
.ambassador-detail__timeline {
    list-style: none;
    margin: 0; padding: 0;
    position: relative;
}
.ambassador-detail__timeline::before {
    content: '';
    position: absolute;
    left: 11px; top: 6px; bottom: 6px;
    width: 2px;
    background: var(--border);
}
.ambassador-detail__timeline-item {
    position: relative;
    padding-left: 2.25rem;
    padding-bottom: 1.1rem;
}
.ambassador-detail__timeline-item:last-child { padding-bottom: 0; }
.ambassador-detail__timeline-marker {
    position: absolute;
    left: 5px; top: 8px;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--surface);
    border: 2px solid var(--border);
    z-index: 1;
}
.ambassador-detail__timeline-item.is-current .ambassador-detail__timeline-marker {
    background: var(--accent);
    border-color: var(--accent);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent);
}
.ambassador-detail__timeline-head {
    display: flex; align-items: baseline; gap: .5rem;
    flex-wrap: wrap;
    margin-bottom: .15rem;
}
.ambassador-detail__timeline-rate {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}
.ambassador-detail__timeline-item:not(.is-current) .ambassador-detail__timeline-rate {
    color: var(--muted);
}
.ambassador-detail__timeline-pill {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    background: var(--accent);
    color: var(--surface);
    padding: .12rem .55rem;
    border-radius: 999px;
    font-weight: 700;
}
.ambassador-detail__timeline-period {
    font-size: .88rem;
    color: var(--text);
    margin-bottom: .2rem;
}
.ambassador-detail__timeline-period strong { font-feature-settings: "tnum"; }
.ambassador-detail__timeline-note {
    font-size: .85rem;
    color: var(--muted);
    font-style: italic;
}

/* === Ambassador Compta tab — header CTA + payouts table polish ============ */
.ambassador-compta__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; margin-bottom: .85rem;
}
.ambassador-compta__cta {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .5rem .9rem;
    font-size: .9rem;
    white-space: nowrap;
    flex-shrink: 0;
}
.ambassador-compta__cta-icon { width: 14px; height: 14px; flex-shrink: 0; }

.ambassador-detail__payouts-table { table-layout: fixed; width: 100%; }
/* Percentage widths so the table re-balances itself at every panel size
 * (the panel is much wider in fullscreen than in mobile-narrow). The
 * previous mix of fixed rem widths with ONE auto column gave the auto
 * column all the slack on a wide screen, blowing out Méthode. */
.ambassador-compta__col-date    { width: 20%; }
.ambassador-compta__col-amount  { width: 16%; text-align: right; }
.ambassador-compta__col-method  { width: 24%; }
.ambassador-compta__col-docs    { width: 28%; }
.ambassador-compta__col-actions { width: 12%; text-align: right; }

/* Méthode cells with a payment reference: dotted underline + cursor:help
 * + a CSS-only tooltip that appears instantly on hover. We don't rely
 * on the browser's native title= because the delay (500-1500ms) makes
 * users think nothing happens. */
.ambassador-compta__method-with-ref {
    position: relative;
    text-decoration: underline dotted;
    text-decoration-color: var(--muted);
    text-underline-offset: 3px;
    cursor: help;
}
.ambassador-compta__method-with-ref::after {
    content: attr(data-tip);
    position: absolute;
    left: 0;
    top: calc(100% + 8px);
    background: var(--primary);
    color: var(--surface);
    padding: .35rem .65rem;
    border-radius: 6px;
    font-size: .78rem;
    font-weight: 500;
    white-space: nowrap;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .2);
    opacity: 0;
    pointer-events: none;
    transition: opacity .12s ease;
    z-index: 100;
}
/* Tooltip arrow pointing UP to the word above. We anchor the tooltip
 * BELOW the cell by default because the row's neighbours (and any
 * potential overflow clipping above) would crop a tooltip rendered
 * above. The last-rows override below flips it back to "above" when
 * there's no room below. */
.ambassador-compta__method-with-ref::before {
    content: '';
    position: absolute;
    left: 1.25rem;
    top: calc(100% + 3px);
    border: 5px solid transparent;
    border-bottom-color: var(--primary);
    opacity: 0;
    pointer-events: none;
    transition: opacity .12s ease;
    z-index: 100;
}
.ambassador-compta__method-with-ref:hover::after,
.ambassador-compta__method-with-ref:hover::before,
.ambassador-compta__method-with-ref:focus::after,
.ambassador-compta__method-with-ref:focus::before {
    opacity: 1;
}

/* Last row(s) of the payouts table — flip the tooltip ABOVE the word
 * because the section bottom edge clips a tooltip pointing down. The
 * rows above always have a table header / earlier row so an upward
 * tooltip stays visible. We cover the last 2 rows so a 1-row table
 * also flips properly. */
.ambassador-detail__payouts-table tbody tr:nth-last-child(-n+2) .ambassador-compta__method-with-ref::after {
    top: auto;
    bottom: calc(100% + 8px);
}
.ambassador-detail__payouts-table tbody tr:nth-last-child(-n+2) .ambassador-compta__method-with-ref::before {
    top: auto;
    bottom: calc(100% + 3px);
    border-bottom-color: transparent;
    border-top-color: var(--primary);
}
.ambassador-detail__payouts-table th,
.ambassador-detail__payouts-table td {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    vertical-align: middle;
    padding: .55rem .5rem;
}
/* The "Documents" column needs to keep its inline-flex children visible
 * — re-enabling overflow so the icon row isn't clipped when the column
 * is narrow on a narrow panel. */
.ambassador-detail__payouts-table td.ambassador-compta__col-docs,
/* Méthode cell: same opt-out so the hover tooltip pseudo-element above
 * the underlined word can escape the cell box (the default cell
 * overflow:hidden was clipping it). */
.ambassador-detail__payouts-table td.ambassador-compta__col-method {
    overflow: visible; text-overflow: clip;
}
.ambassador-detail__payouts-table .ambassador-compta__col-method small { display: block; }

/* SVG icons in the Documents column — uniform line-icon size + hover. */
.ambassador-compta__doc-icons {
    display: inline-flex; align-items: center; gap: .25rem;
}
.ambassador-compta__doc-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px;
    border-radius: 6px;
    color: var(--muted);
    text-decoration: none;
    transition: color .12s, background .12s;
    /* Same class on <a> (invoice link) and <button> (proof viewer
     * trigger) — strip the button chrome so they match visually. */
    appearance: none;
    background: transparent;
    border: 0;
    cursor: pointer;
    padding: 0;
}
.ambassador-compta__doc-icon svg { width: 16px; height: 16px; }
.ambassador-compta__doc-icon:hover { color: var(--primary); background: var(--surface-alt); }

/* Action button: stronger visual weight at rest so the operator spots
 * it immediately when scanning the row (the user explicitly asked for
 * the actions to be prioritised). Solid border, accent-tinted bg. */
.ambassador-compta__doc-add {
    appearance: none;
    width: 28px; height: 28px;
    border: 1px solid var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border-radius: 6px;
    color: var(--primary-dark);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: color .12s, background .12s, border-color .12s;
    padding: 0;
}
.ambassador-compta__doc-add svg { width: 14px; height: 14px; }
.ambassador-compta__doc-add:hover {
    background: var(--accent);
    color: var(--surface);
}

/* Cancel-payout icon button: still subtle by default (destructive but
 * rarely used) but visible enough to notice — outlined ghost style. */
.ambassador-compta__void-btn {
    appearance: none;
    background: transparent;
    border: 1px solid var(--border);
    width: 28px; height: 28px;
    border-radius: 50%;
    color: var(--muted);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: color .12s, background .12s, border-color .12s;
    padding: 0;
}
.ambassador-compta__void-btn svg { width: 16px; height: 16px; }
.ambassador-compta__void-btn:hover {
    color: var(--danger, #b94a48);
    border-color: var(--danger, #b94a48);
    background: color-mix(in srgb, var(--danger, #b94a48) 12%, transparent);
}

/* === Ambassador modals — styled dropzone file input ====================
 * Replaces the native <input type="file"> chrome (which clashes hard
 * with the rest of the modal) by a click-anywhere dashed area. The
 * underlying input is visually hidden but still in the form, so the
 * submit ships the file unchanged. Drag-and-drop is wired by JS. */
.ambassador-dropzone-field {
    display: flex; flex-direction: column; gap: .35rem;
}
.ambassador-dropzone-field__label {
    font-size: .85rem;
    font-weight: 600;
    color: var(--text);
}
.ambassador-dropzone {
    position: relative;
    display: flex; align-items: center; gap: .85rem;
    padding: .85rem 1rem;
    border: 1.5px dashed var(--border);
    border-radius: 10px;
    background: var(--surface-alt);
    cursor: pointer;
    transition: border-color .15s, background .15s;
}
.ambassador-dropzone:hover,
.ambassador-dropzone:focus-within {
    border-color: var(--primary);
    background: var(--surface);
}
.ambassador-dropzone.is-dragging {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 12%, var(--surface) 88%);
}
.ambassador-dropzone.has-file {
    border-style: solid;
    border-color: var(--primary);
    background: var(--surface);
}
.ambassador-dropzone__input {
    /* Visually hidden but still focusable + ships the file. */
    position: absolute;
    opacity: 0;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}
.ambassador-dropzone__icon {
    width: 28px; height: 28px;
    color: var(--muted);
    flex-shrink: 0;
}
.ambassador-dropzone.has-file .ambassador-dropzone__icon { color: var(--primary); }
.ambassador-dropzone__text {
    display: flex; flex-direction: column; gap: .15rem;
    min-width: 0; flex: 1;
}
.ambassador-dropzone__text strong {
    font-size: .92rem;
    color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ambassador-dropzone__text span {
    font-size: .78rem;
    color: var(--muted);
}

/* === Contract section — header actions + signed-version sign form === */
.ambassador-contract__actions {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
    align-items: center;
}
.ambassador-contract__sign-form {
    margin-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .85rem;
    align-items: stretch;
}
.ambassador-contract__sign-form .btn {
    align-self: flex-start;
}
.ambassador-contract__history {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px dashed var(--border);
}
.ambassador-contract__history > summary {
    cursor: pointer;
    font-size: .9rem;
    font-weight: 600;
    color: var(--muted);
    user-select: none;
    list-style: revert;
}
.ambassador-contract__history > summary:hover {
    color: var(--text);
}
.ambassador-contract__history-table {
    margin-top: .85rem;
    font-size: .9rem;
}

/* === "À traiter" banner on /admin/ambassadeurs =========================
 * Surfaces ambassadors with a positive balance + last payout > 60 days
 * (or never), so the admin doesn't have to leave the list to /compta to
 * notice an overdue settlement. */
.ambassador-todo-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap; /* narrow screens: "Aller à la comptabilité" wraps below */
    gap: .65rem;
    padding: .85rem 1.1rem;
    margin: 0 0 1.25rem;
    background: #fff8eb;
    border: 1px solid #e3c55a;
    border-radius: 10px;
    color: var(--text);
    font-size: .92rem;
    text-decoration: none;
    transition: background .15s, border-color .15s;
}
.ambassador-todo-banner:hover { background: #fff2d4; border-color: #c9a227; }
.ambassador-todo-banner svg   { width: 18px; height: 18px; color: #c9a227; flex-shrink: 0; }
.ambassador-todo-banner strong { color: var(--text); }

/* === Ambassador dashboard chart tooltip ================================
 * Pinned to the cursor on hover of any [data-bar]. Inline JS in the
 * dashboard view positions it (clientX/Y + scroll). Z-index above
 * the page so it never gets clipped by section padding. */
.ambassador-chart-tooltip {
    position: absolute;
    z-index: 50;
    pointer-events: none;
    background: var(--text);
    color: var(--bg);
    padding: .55rem .75rem;
    border-radius: 6px;
    font-size: .82rem;
    line-height: 1.45;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
    white-space: nowrap;
    transform: translate(0, -100%);
}
.ambassador-chart-tooltip strong {
    text-transform: capitalize;
    font-weight: 600;
}
.ambassador-chart-tooltip__amount {
    color: #d9b94d;
    font-weight: 600;
}
/* Hover band on the chart: subtle highlight on the slot the cursor is
 * over, to confirm interactivity. */
svg [data-bar]:hover {
    fill: rgba(201, 162, 39, .08);
}

/* === Documents joints — open-in-viewer button (looks like a link) ==== */
.ambassador-document__open {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    color: var(--primary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font: inherit;
    text-align: left;
}
.ambassador-document__open:hover { text-decoration: underline; }
.ambassador-document__open svg   { width: 14px; height: 14px; flex-shrink: 0; }

/* === Document viewer modal — justificatif, facture, ... ============== */
.ambassador-modal--viewer {
    width: min(900px, calc(100vw - 2rem));
}
.ambassador-modal__viewer-body {
    padding: 0;
    background: #2b2b2b;
    min-height: 60vh;
    max-height: 75vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: auto;
}
.ambassador-modal__viewer-frame {
    width: 100%;
    height: 75vh;
    border: 0;
    background: #fff;
    display: block;
}
.ambassador-modal__viewer-img {
    max-width: 100%;
    max-height: 75vh;
    width: auto;
    height: auto;
    display: block;
    object-fit: contain;
}

/* === Onboarding — setup gate ============================================ */

/* Persistent banner below the header while the configuration is incomplete. */
.admin-setup-banner {
    display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: .25rem 1rem;
    background: rgba(201, 162, 39, .14);
    border-bottom: 1px solid rgba(201, 162, 39, .5);
    color: var(--text);
    padding: .7rem 1.25rem;
    font-size: .92rem;
    text-align: center;
}
.admin-setup-banner a {
    color: var(--primary-dark, var(--primary));
    font-weight: 700;
    white-space: nowrap;
}

/* Onboarding dashboard — intro block + CTA. */
.onboarding-intro { max-width: 720px; margin: 0 0 1.5rem; }
.onboarding-intro h1 { margin: 0 0 .5rem; }
.onboarding-intro p { color: var(--muted); line-height: 1.55; margin: 0; }
.onboarding-cta { margin: 1.1rem 0 0; }

/* .env pre-flight diagnostic card. */
.setup-preflight {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius, 10px);
    padding: 1.1rem 1.25rem;
    margin: 1.5rem 0 0;
}
.setup-preflight h2 { margin: 0 0 .35rem; font-size: 1.1rem; }
.setup-preflight__intro { color: var(--muted); font-size: .9rem; line-height: 1.5; margin: 0 0 .9rem; }
.setup-preflight__intro code,
.setup-preflight__body code {
    background: var(--surface-alt, rgba(0,0,0,.05));
    border-radius: 4px; padding: .05rem .35rem; font-size: .85em;
}
.setup-preflight__list { list-style: none; margin: 0; padding: 0; }
.setup-preflight__item {
    display: flex; gap: .65rem; align-items: flex-start;
    padding: .55rem 0; border-top: 1px solid var(--border);
}
.setup-preflight__item:first-child { border-top: none; }
.setup-preflight__mark {
    flex: 0 0 auto; width: 1.4rem; height: 1.4rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: .8rem; font-weight: 700;
}
.setup-preflight__item.is-ok  .setup-preflight__mark { background: var(--primary); color: var(--surface); }
.setup-preflight__item.is-ko  .setup-preflight__mark { background: #b3261e; color: #fff; }
.setup-preflight__body { display: flex; flex-direction: column; gap: .15rem; }
.setup-preflight__body strong { color: var(--text); }
.setup-preflight__body code { align-self: flex-start; }
.setup-preflight__hint { color: var(--muted); font-size: .86rem; line-height: 1.45; }

/* === VAT franchise alert (dashboard) ==================================== */
.vat-alert {
    border-radius: var(--radius, 10px);
    border: 1px solid;
    padding: .9rem 1.15rem;
    margin: 0 0 1.5rem;
}
.vat-alert strong { display: block; }
.vat-alert p { margin: .25rem 0 0; font-size: .92rem; line-height: 1.5; }
.vat-alert--warning {
    background: rgba(201, 162, 39, .12);
    border-color: rgba(201, 162, 39, .55);
}
.vat-alert--exceeded {
    background: rgba(179, 38, 30, .09);
    border-color: rgba(179, 38, 30, .45);
}
.vat-alert--exceeded strong { color: #b3261e; }

/* ======================================================================
 * Book detail panel — dashboard-style layout
 * ======================================================================
 * Replaces the old single "Détails" table + flat sales summary. Sections
 * each fit on one screen of the slide-in panel; the KPI strip is the at-
 * a-glance landing surface, every following block is a navigable summary
 * card with a "Modifier le …" deep-link to the right tab of the edit form.
 */
.book-detail__meta-line {
    margin: 0;
    color: var(--muted);
    font-size: .82rem;
}

.book-detail__kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: .65rem;
    margin: 0 0 1.5rem;
}
.book-detail__kpi {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    padding: .65rem .85rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    min-width: 0;
}
.book-detail__kpi-label {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    font-weight: 600;
}
.book-detail__kpi-value {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--primary);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.book-detail__kpi-flag {
    display: block;
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-top: .1rem;
}
.book-detail__kpi--warn {
    background: rgba(201, 162, 39, .12);
    border-color: rgba(201, 162, 39, .45);
}
.book-detail__kpi--warn .book-detail__kpi-value,
.book-detail__kpi--warn .book-detail__kpi-flag { color: #7a5e0f; }
.book-detail__kpi--alert {
    background: rgba(179, 38, 30, .09);
    border-color: rgba(179, 38, 30, .45);
}
.book-detail__kpi--alert .book-detail__kpi-value,
.book-detail__kpi--alert .book-detail__kpi-flag { color: #b3261e; }

.book-detail__block {
    margin: 0 0 1.5rem;
    padding: 0;
}
.book-detail__block-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin: 0 0 .65rem;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--border-soft);
}
.book-detail__block-head h2 {
    margin: 0;
    font-size: 1.05rem;
}
.book-detail__block-edit {
    font-size: .82rem;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
}
.book-detail__block-edit:hover { text-decoration: underline; }

.book-detail__dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 1rem;
    row-gap: .35rem;
    margin: 0;
    font-size: .9rem;
}
.book-detail__dl dt {
    color: var(--muted);
    font-weight: 600;
}
.book-detail__dl dd {
    margin: 0;
    color: var(--text);
    overflow-wrap: anywhere;
}
.book-detail__dl code {
    background: var(--surface-alt);
    padding: 0 .3rem;
    border-radius: 4px;
    font-size: .85em;
}

.book-detail__resources {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}
.book-detail__resources li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .45rem .65rem;
    background: var(--surface-alt);
    border-radius: 6px;
    font-size: .9rem;
}
.book-detail__resources li > :first-child {
    font-weight: 600;
    color: var(--text);
}
.book-detail__resources li a { color: var(--primary); text-decoration: none; }
.book-detail__resources li a:hover { text-decoration: underline; }
.book-detail__resources li > :last-child {
    color: var(--muted);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.book-detail__resources li code {
    background: transparent;
    color: var(--muted);
    font-size: .85em;
}

.book-detail__hint {
    margin: .5rem 0 0;
    font-size: .85rem;
    color: var(--muted);
    line-height: 1.5;
}
.book-detail__hint--warn {
    color: #7a5e0f;
    background: rgba(201, 162, 39, .12);
    border-left: 3px solid rgba(201, 162, 39, .55);
    padding: .55rem .75rem;
    border-radius: 0 6px 6px 0;
}

.book-detail__foot {
    margin-top: 2rem;
    padding-top: .85rem;
    border-top: 1px solid var(--border-soft);
    font-size: .78rem;
    color: var(--muted);
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    align-items: center;
}
.book-detail__foot a {
    color: var(--primary);
    text-decoration: none;
}
.book-detail__foot a:hover { text-decoration: underline; }

/* ======================================================================
 * Admin books list — richer columns (cover thumb, format chips, stock,
 * completeness flag).
 * ====================================================================== */
.books-list { table-layout: auto; }
.books-list__col-cover   { width: 56px; }
.books-list__col-format  { width: 8rem; }
.books-list__col-status  { width: 7rem; }
.books-list__col-price   { width: 7rem; text-align: right; }
.books-list__col-stock   { width: 5rem; text-align: right; }
.books-list__col-release { width: 8.5rem; }
.books-list__col-ready   { width: 4rem; text-align: center; }

.books-list__cell-cover { padding: .4rem .3rem .4rem .9rem; }
.books-list__cover {
    display: block;
    width: 36px; height: 54px;
    object-fit: cover;
    border-radius: 3px;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
}
.books-list__cover--placeholder {
    background: repeating-linear-gradient(
        45deg,
        var(--surface-alt) 0 4px,
        rgba(0,0,0,.04) 4px 8px
    );
}
.books-list__subtitle {
    font-size: .8rem;
    font-style: italic;
    margin-top: .15rem;
}
.books-list__format-chip {
    display: inline-block;
    padding: .1rem .45rem;
    border-radius: 4px;
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    line-height: 1.5;
    margin-right: .2rem;
}
.books-list__format-chip--digital {
    background: rgba(59, 130, 246, .12);
    color: #1e40af;
}
.books-list__format-chip--physical {
    background: rgba(217, 119, 6, .15);
    color: #92400e;
}
.books-list__cell-price div { font-variant-numeric: tabular-nums; }
.books-list__cell-price .muted { font-size: .8rem; }
.books-list__cell-stock { font-variant-numeric: tabular-nums; }
.books-list__stock small {
    display: block;
    font-size: .7rem;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.books-list__stock--low { color: #7a5e0f; font-weight: 600; }
.books-list__stock--low small { color: #7a5e0f; }
.books-list__stock--out { color: #b3261e; font-weight: 700; }
.books-list__stock--out small { color: #b3261e; }

.books-list__ready {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.8rem;
    height: 1.5rem;
    border-radius: 12px;
    font-size: .8rem;
    font-weight: 700;
    padding: 0 .5rem;
    cursor: help;
}
.books-list__ready--ok {
    background: rgba(4, 120, 87, .16);
    color: #065f46;
}
.books-list__ready--ko {
    background: rgba(201, 162, 39, .2);
    color: #7a5e0f;
}

/* ======================================================================
 * Book form — overview pane (apercu)
 * ====================================================================== */
.form-overview-checklist {
    margin: 0 0 1.5rem;
    padding: 1rem 1.15rem;
    background: var(--surface-alt);
    border: 1px solid var(--border-soft);
    border-radius: 10px;
}
.form-overview-checklist h3 {
    margin: 0 0 .5rem;
    font-size: 1rem;
}
.form-overview-checklist__ok {
    margin: 0;
    color: #065f46;
    font-weight: 600;
}
.form-overview-checklist__intro {
    margin: 0 0 .65rem;
    color: var(--muted);
    font-size: .9rem;
}
.form-overview-checklist__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .4rem;
}
.form-overview-checklist__list li {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .45rem .65rem;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    font-size: .9rem;
}
.form-overview-checklist__icon {
    color: #7a5e0f;
    font-weight: 700;
}
.form-overview-checklist__label { flex: 1; min-width: 0; }
.form-overview-checklist__jump {
    color: var(--primary);
    text-decoration: none;
    font-size: .82rem;
    white-space: nowrap;
}
.form-overview-checklist__jump:hover { text-decoration: underline; }

.form-section-rule {
    border: 0;
    border-top: 1px solid var(--border-soft);
    margin: 1.5rem 0 .25rem;
}

.archive-form {
    background: rgba(179, 38, 30, .04);
    border: 1px solid rgba(179, 38, 30, .25);
    border-radius: 8px;
    padding: 1rem 1.15rem;
    margin: 0;
}

/* Native <fieldset> styling reset for the physical-edition block + faded
 * look when the "Édition papier" toggle is off. `disabled` is set by JS in
 * book-form.php to actually prevent input, and we mirror it visually. */
.physical-block {
    border: 0;
    padding: 0;
    margin: 0;
    min-inline-size: 0;
}
.physical-block[disabled] {
    opacity: .45;
    pointer-events: none;
    filter: grayscale(.4);
}

.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* =====================================================================
   Tracking dashboard — /admin/ventes/expeditions
   Cards-of-shipments view with a 4-step progress bar coloured by parcel
   age (green < 5 j, orange 5–10 j, red > 10 j). Reads the cron-maintained
   snapshot from purchase_shipments; the "Rafraîchir" button forces a poll.
   ===================================================================== */
.shipments-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
    gap: 1rem;
}
.shipment-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-left: 4px solid var(--primary); /* tone strip — overridden per tone below */
    border-radius: var(--radius);
    padding: 1rem 1.1rem;
    box-shadow: var(--shadow-sm);
    display: flex; flex-direction: column; gap: .85rem;
    min-width: 0;
}
.shipment-card--ok   { border-left-color: var(--primary); }
.shipment-card--slow { border-left-color: #d97706; }       /* orange */
.shipment-card--late { border-left-color: #b94a3b; }       /* red   */
.shipment-card__head { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.shipment-card__title { font-size: 1rem; overflow-wrap: anywhere; }
.shipment-card__meta  { font-size: .85rem; color: var(--text); display: flex; flex-wrap: wrap; gap: .35rem; overflow-wrap: anywhere; }
.shipment-card__event { margin: 0; font-size: .9rem; line-height: 1.4; overflow-wrap: anywhere; }
.shipment-card__foot {
    display: flex; justify-content: space-between; align-items: center;
    gap: .5rem; flex-wrap: wrap;
    border-top: 1px solid var(--border-soft); padding-top: .75rem;
}
.shipment-card__carrier {
    display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
    font-size: .85rem;
}
.shipment-card__carrier code {
    font-size: .82rem; background: var(--surface-alt); padding: .12rem .4rem;
    border-radius: 4px; overflow-wrap: anywhere;
}
.shipment-card__actions { display: flex; gap: .4rem; flex-wrap: wrap; }
.shipment-card__actions .btn-sm { padding: .35rem .7rem; font-size: .85rem; }

/* ── 4-step progress bar ──
   Each step is a flex item with a dot above its label and a connector line
   to the next dot. The colour follows the parent .shipment-card--{tone} so
   age-urgency tints the whole timeline. */
.shipment-progress {
    list-style: none; padding: 0; margin: 0;
    display: flex; align-items: flex-start; gap: 0;
    counter-reset: ship-step;
}
.shipment-progress__step {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; align-items: center;
    text-align: center; position: relative;
    color: var(--muted); font-size: .72rem; line-height: 1.2;
}
.shipment-progress__dot {
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--surface-alt);
    border: 2px solid var(--border);
    margin-bottom: .4rem;
    flex-shrink: 0;
    z-index: 1;
}
/* Connector line between dots — drawn as a pseudo-element on every step
   except the last, anchored to the dot's vertical center. */
.shipment-progress__step:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 8px; /* (dot height 14 + border 2*2) / 2 ≈ 8px from the top of the dot */
    left: 50%;
    width: 100%;
    height: 2px;
    background: var(--border);
    z-index: 0;
}
.shipment-progress__label { padding: 0 .15rem; overflow-wrap: anywhere; }

/* Step states — done / current / todo. The card's --tone-color drives the
   final hue so an "ok" card stays green, a "late" card paints the whole
   bar red, etc. */
.shipment-card--ok   { --tone-color: var(--primary); }
.shipment-card--slow { --tone-color: #d97706; }
.shipment-card--late { --tone-color: #b94a3b; }

.shipment-progress__step--done .shipment-progress__dot,
.shipment-progress__step--current .shipment-progress__dot {
    background: var(--tone-color);
    border-color: var(--tone-color);
}
.shipment-progress__step--done::after { background: var(--tone-color); }
.shipment-progress__step--current .shipment-progress__label {
    color: var(--tone-color);
    font-weight: 600;
}
.shipment-progress__step--current .shipment-progress__dot {
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--tone-color) 20%, transparent);
}

/* Mobile: cards take full width, progress dots stay legible, labels
   shrink one step. */
@media (max-width: 480px) {
    .shipments-grid { grid-template-columns: 1fr; }
    .shipment-progress__label { font-size: .65rem; }
    .shipment-progress__dot { width: 12px; height: 12px; }
}

/* ============================================================================
 * UX tuning (audit admin 2026-05-30) — allègement du rythme + composants
 * de progressive disclosure. Ajouté en fin de feuille pour primer sur les
 * règles de base à spécificité égale. Voir docs/ux-audit-admin.md.
 * ========================================================================== */

/* L3 — Rythme vertical resserré (titres + cartes de stats). */
h1 { margin-bottom: 1rem; }
h2 { margin-bottom: .75rem; }
.dashboard-stat { padding: 1.1rem 1.25rem; }
.dashboard-stat__value { font-size: 1.6rem; }

/* C2 — Astérisque « champ requis ». */
.field-required { color: #b3261e; font-weight: 700; }

/* I1 / V2 / T2 — Sections repliables (progressive disclosure).
 * <details class="form-advanced-section"> avec un <summary> à deux lignes. */
.form-advanced-section {
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface-alt, rgba(0,0,0,.02));
    margin: 1rem 0;
}
.form-advanced-section > summary {
    cursor: pointer;
    list-style: none;
    padding: .7rem .9rem;
    display: flex;
    flex-direction: column;
    gap: .1rem;
    border-radius: 8px;
}
.form-advanced-section > summary::-webkit-details-marker { display: none; }
.form-advanced-section > summary::after {
    content: '▸';
    position: absolute;
    right: 1rem;
    color: var(--muted);
    transition: transform .15s ease;
}
.form-advanced-section[open] > summary::after { transform: rotate(90deg); }
.form-advanced-section > summary { position: relative; }
.form-advanced-section__title { font-weight: 600; font-size: .95rem; }
.form-advanced-section__hint { font-size: .8rem; }
.form-advanced-section__body { padding: 0 .9rem 1rem; }
.form-advanced-section--danger { border-color: rgba(179,38,30,.35); }
.form-advanced-section--danger .form-advanced-section__title { color: #b3261e; }

/* E1 — Variante « avancé » du séparateur de famille d'onglets. */
.settings-tabs__sep--advanced { opacity: .75; }

/* ──────────────────────────────────────────────────────────────────────────
   Dashboard — UX pass (D1-D7)
   D1 « À traiter » remonté en tête, pleine largeur, accent visuel.
   D3 graphique des visites repliable. D4 note moyenne condensée.
   D5 lignes de tableau cliquables (.js-row-link). D6 rythme vertical.
   ────────────────────────────────────────────────────────────────────────── */

/* D1 — call-out « À traiter » en tête de page */
.dashboard-todo {
    margin: 0 0 1.5rem;
    padding: 1rem 1.25rem;
    background: var(--surface, #fff);
    border: 1px solid var(--border-soft, #e6e2da);
    border-left: 4px solid var(--accent, #b8704f);
    border-radius: 10px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}
.dashboard-todo__title {
    margin: 0 0 .65rem;
    font-size: 1rem;
    font-weight: 700;
}
.dashboard-todo__list {
    margin: 0;
}
/* deux colonnes sur large écran quand plusieurs actions, une seule en mobile */
@media (min-width: 760px) {
    .dashboard-todo__list {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
        gap: .35rem .9rem;
    }
}
.dashboard-todo__hint {
    color: var(--muted, #8a8178);
    font-weight: 400;
    margin-left: .25rem;
}

/* D4 — note moyenne sur une ligne compacte */
.rating-inline {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem .75rem;
    margin: 0;
}
.rating-inline__stars { line-height: 1; }
.rating-inline__score { font-weight: 700; }
.rating-inline__count {
    color: var(--muted, #8a8178);
    font-size: .9rem;
}

/* D5 — lignes de tableau cliquables (sans onclick inline) */
tr.js-row-link { cursor: pointer; }
tr.js-row-link:hover { background: var(--row-hover, rgba(0, 0, 0, .03)); }
tr.js-row-link:focus-visible {
    outline: 2px solid var(--accent, #b8704f);
    outline-offset: -2px;
}

/* D2 — la carte « Depuis le lancement » a été fusionnée dans les KPI du haut.
   La rangée du bas peut donc n'avoir qu'une seule carte (« Pré-commandes ») :
   on la laisse occuper toute la largeur plutôt qu'un demi-vide à droite. */
.dashboard-bottom:has(> .dashboard-card:only-child) {
    grid-template-columns: 1fr;
}

/* Insights sur 3 colonnes : Top 3 · Note moyenne · Visites (côte à côte).
   align-items:start pour que la note (1 ligne) ne s'étire pas en grande
   carte vide ; le graphe garde sa hauteur naturelle à droite. */
.dashboard-insights.dashboard-insights--3col {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, .85fr) minmax(0, 1.45fr);
    align-items: start;
}
.dashboard-insights--3col > .dashboard-chart-card {
    width: 100%;
    min-width: 0;
}
@media (max-width: 1080px) {
    .dashboard-insights.dashboard-insights--3col { grid-template-columns: 1fr; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Ventes — passe UX (VL1-VL3, VP1-VP2, VD1-VD4, VX1)
   ────────────────────────────────────────────────────────────────────────── */

/* VL1 — graphe « Activité commerciale » repliable */
.sales-chart-details {
    margin: 0 0 1.25rem;
    border: 1px solid var(--border-soft, #e6e2da);
    border-radius: 10px;
    background: var(--surface, #fff);
}
.sales-chart-details > .sales-chart-card { margin: 0; border: 0; }
.sales-chart-details__summary {
    display: flex; align-items: baseline; gap: 1rem;
    padding: .8rem 1.1rem; cursor: pointer; font-weight: 600; list-style: none;
}
.sales-chart-details__summary::-webkit-details-marker { display: none; }
.sales-chart-details__summary::before {
    content: "▸"; color: var(--muted, #8a8178);
    transition: transform .15s ease; display: inline-block;
}
.sales-chart-details[open] .sales-chart-details__summary::before { transform: rotate(90deg); }
.sales-chart-details__hint { color: var(--muted, #8a8178); font-weight: 500; font-size: .9rem; }

/* VL2 — badges « statut effectif » (logistique fusionnée au paiement) */
.status-badge--needs-ship { background: #f6c544; color: #3d2c00; }
.status-badge--shipped    { background: #d9e6f2; color: #1f3a52; }
.status-badge--delivered  { background: #d8efe0; color: #14502f; }

/* VD1 — bouton d'action principale en tête de la fiche vente */
.sale-primary-cta {
    display: inline-flex; align-items: center; gap: .4rem;
    margin: 0 0 1.25rem;
}

/* VP1/VD2 + VD3 — blocs techniques / historiques repliés */
.tech-details, .trail-details {
    margin: .75rem 0 0;
    border-top: 1px solid var(--border-soft, #e6e2da);
    padding-top: .6rem;
}
.tech-details > summary, .trail-details > summary {
    cursor: pointer; color: var(--muted, #8a8178);
    font-size: .9rem; list-style: none;
}
.tech-details > summary::-webkit-details-marker,
.trail-details > summary::-webkit-details-marker { display: none; }
.tech-details > summary::before, .trail-details > summary::before {
    content: "▸ "; color: var(--muted, #8a8178);
}
.tech-details[open] > summary::before, .trail-details[open] > summary::before { content: "▾ "; }
.tech-details__list { list-style: none; margin: .6rem 0 0; padding: 0; }
.tech-details__list li {
    display: flex; justify-content: space-between; gap: 1rem;
    padding: .3rem 0; font-size: .85rem; border-top: 1px solid var(--border-soft, #efeae1);
}
.tech-details__list span { color: var(--muted, #8a8178); }
.tech-details__list code { font-size: .8rem; word-break: break-all; text-align: right; }

/* VX1/VP2 — APERÇU vente : masqué partout, affiché seulement dans le drawer */
[data-sale-apercu] { display: none; }
.sale-panel__body [data-sale-apercu] { display: block; padding: 1.25rem 1.4rem; }
.sale-apercu__head {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 1rem; flex-wrap: wrap;
}
.sale-apercu__eyebrow {
    margin: 0; text-transform: uppercase; letter-spacing: .06em;
    font-size: .72rem; color: var(--muted, #8a8178);
}
.sale-apercu__title { margin: .1rem 0 .4rem; font-size: 1.25rem; }
.sale-apercu__stats {
    list-style: none; margin: 1.1rem 0; padding: .9rem 0;
    border-top: 1px solid var(--border-soft, #e6e2da);
    border-bottom: 1px solid var(--border-soft, #e6e2da);
    display: grid; grid-template-columns: 1fr 1fr; gap: .75rem 1.25rem;
}
.sale-apercu__stats li { display: flex; flex-direction: column; min-width: 0; }
.sale-apercu__stats span {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted, #8a8178);
}
.sale-apercu__stats strong { font-size: .95rem; overflow-wrap: anywhere; }
.sale-apercu__lines { margin: 0; }
.sale-apercu__lines p { margin: .35rem 0; font-size: .92rem; }
.sale-apercu__todo {
    background: rgba(246, 197, 68, .15); border-radius: 6px;
    padding: .45rem .65rem; font-weight: 600;
}
.sale-apercu__hint { margin: 1rem 0 0; font-size: .82rem; color: var(--muted, #8a8178); font-style: italic; }

/* VD4 — cibles tactiles ≥ 44px sur mobile (page vente + drawer) */
@media (max-width: 720px) {
    [data-sale-detail] .btn,
    [data-sale-detail] button,
    [data-sale-detail] input:not([type=checkbox]):not([type=radio]),
    [data-sale-detail] select,
    .sale-panel__body .btn,
    .sale-panel__close { min-height: 44px; }
    .sale-apercu__head .btn { width: 100%; justify-content: center; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Avis + Messages — passe UX (MS1-MS3, AV1-AV3)
   ────────────────────────────────────────────────────────────────────────── */

/* MS1 — détail message dans le drawer (réutilise .sale-panel) */
[data-message-fullscreen] { display: none; }
.sale-panel__body [data-message-card] { padding: 1.25rem 1.4rem; }
.sale-panel__body [data-message-card] h1 { font-size: 1.3rem; margin-top: 0; }
.sale-panel__body [data-message-fullscreen] { display: inline-flex; }

/* AV3 — cibles tactiles ≥ 44px (boutons d'action Avis) sur mobile */
@media (max-width: 720px) {
    .reviews-action-btn,
    .reviews-table__expand,
    .reviews-bulk-bar .btn { min-height: 44px; }
    .reviews-table td { padding-top: .6rem; padding-bottom: .6rem; }
    .msg-row td { padding-top: .65rem; padding-bottom: .65rem; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Ambassadeurs — refonte UX (AB2-AB15)
   ────────────────────────────────────────────────────────────────────────── */

/* AB6 — barre de sous-onglets unifiée de l'univers Ambassadeurs. */
.amb-subnav {
    display: flex; gap: .25rem; flex-wrap: wrap;
    margin: 0 0 1.25rem;
    border-bottom: 1px solid var(--border);
}
.amb-subnav__tab {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .55rem .9rem;
    border-bottom: 2px solid transparent;
    color: var(--muted);
    font-size: .92rem; font-weight: 500;
    text-decoration: none;
    transition: color .12s, border-color .12s;
}
.amb-subnav__tab:hover { color: var(--text); }
.amb-subnav__tab.is-active {
    color: var(--primary);
    border-bottom-color: var(--accent);
    font-weight: 600;
}
.amb-subnav__count {
    display: inline-block; min-width: 1.25rem; padding: 0 .35rem;
    background: rgba(201, 162, 39, .18); color: #5c4500;
    border-radius: 999px; font-size: .72rem; font-weight: 700; text-align: center;
}

/* AB4 — bandeau d'état en tête : la prochaine action sous le nom. */
.ambassador-detail__next-action {
    margin: .5rem 0 0; font-size: .92rem;
    background: rgba(201, 162, 39, .1);
    border-left: 3px solid var(--accent, #c9a227);
    padding: .5rem .75rem; border-radius: 0 6px 6px 0;
}

/* AB5 — parcours d'intégration replié quand l'ambassadeur est actif. */
.ambassador-lifecycle__journey > summary {
    cursor: pointer; color: var(--muted); font-size: .9rem;
    padding: .35rem 0;
}
.ambassador-lifecycle__journey[open] > summary { margin-bottom: .5rem; }

/* AB3 — grille 4 KPI + bouton de versement sur la carte Solde + note réserve. */
.ambassador-detail__kpi-grid--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 900px) {
    .ambassador-detail__kpi-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ambassador-detail__kpi-cta {
    margin-top: .65rem; align-self: flex-start;
    font-size: .82rem; padding: .4rem .8rem;
}
.ambassador-detail__kpi-note {
    margin: .75rem 0 0; font-size: .88rem; color: var(--muted);
}

/* AB12 — aperçu ambassadeur : masqué partout, visible seulement dans le drawer.
   Réutilise le chrome .sale-apercu / .sale-panel des Ventes. */
[data-ambassador-apercu] { display: none; }
.sale-panel__body [data-ambassador-apercu] { display: block; padding: 1.25rem 1.4rem; }
.sale-panel__body [data-ambassador-apercu] .sale-apercu__head .btn { white-space: nowrap; }

/* AB14 — tableaux denses → cartes empilées en mobile (≤720px). Les <td>
   portent un data-label rendu en pseudo-élément côté étiquette. */
@media (max-width: 720px) {
    .ambassador-cards-mobile thead { display: none; }
    .ambassador-cards-mobile,
    .ambassador-cards-mobile tbody,
    .ambassador-cards-mobile tr,
    .ambassador-cards-mobile td { display: block; width: 100%; }
    .ambassador-cards-mobile tr {
        border: 1px solid var(--border);
        border-radius: 8px;
        padding: .5rem .75rem;
        margin-bottom: .75rem;
        background: var(--surface);
    }
    .ambassador-cards-mobile td {
        display: flex; justify-content: space-between; gap: 1rem;
        padding: .4rem 0; border: 0;
        text-align: right;
    }
    .ambassador-cards-mobile td::before {
        content: attr(data-label);
        font-weight: 600; color: var(--muted);
        text-align: left; flex: 0 0 auto;
    }
    .ambassador-cards-mobile td:empty,
    .ambassador-cards-mobile td[data-label=""]:empty { display: none; }
    /* Actions pleine largeur + cibles tactiles ≥ 44px. */
    .ambassador-cards-mobile td .btn,
    .ambassador-cards-mobile td button,
    .ambassador-cards-mobile td form { width: auto; }
    .ambassador-detail__codes-actions { width: 100%; }
    .ambassador-detail__codes-actions .btn,
    .ambassador-detail__codes-actions form,
    .ambassador-detail__codes-actions summary { width: 100%; min-height: 44px; }
}

/* ============================================================
   AB14b — Anti-debordement horizontal residuel des tables de la
   fiche ambassadeur en vue mobile (<=720px).

   Diagnostic par element a 375px (page reelle, ambassadeur 47),
   APRES le passage en cartes des blocs .ambassador-cards-mobile
   existants : 3 elements debordaient encore dans la fiche
   [data-ambassador-detail] :
     - .ambassador-detail__codes-table   sw 525 > cw 299
       (cellule Actions en flex + .ambassador-detail__codes-actions
        en flex-wrap:nowrap : la rangee de boutons poussait la largeur)
     - .ambassador-detail__payouts-table sw 369 > cw 299
       (cellule Methode : longue reference en white-space:nowrap)
     - .admin-table-wrap autour de la table d'historique de contrat
       (.admin-table SANS .ambassador-cards-mobile) sw 542 > cw 301
       (table display:table pleine largeur piegee dans le wrapper
        overflow-x:auto injecte par admin-tables.js)
   Selecteurs ancres sur [data-ambassador-detail] pour battre la
   specificite de base sans !important.
   ============================================================ */
@media (max-width: 720px) {
    /* (a) Les wrappers scrollables de la fiche ne scrollent plus.
           overflow force sur les DEUX axes : overflow-x:visible seul
           est reecrit en auto par le navigateur quand overflow-y
           n'est pas visible (regle CSS du raccourci overflow). */
    [data-ambassador-detail] .ambassador-detail__codes-scroll,
    [data-ambassador-detail] .admin-table-wrap {
        overflow: visible;
        min-width: 0;
    }

    /* (b) Plusieurs tables de la fiche n'ont PAS .ambassador-cards-mobile
           (historique de contrat .ambassador-contract__history-table, factures
           auto-émises et documents joints : de simples .admin-table). En
           display:table pleine largeur, elles débordaient dans le wrapper
           .admin-table-wrap. On les stacke en blocs pleine largeur. Cible :
           toute .admin-table de la fiche qui n'est pas déjà une table-carte. */
    [data-ambassador-detail] table.admin-table:not(.ambassador-cards-mobile),
    [data-ambassador-detail] table.admin-table:not(.ambassador-cards-mobile) > tbody,
    [data-ambassador-detail] table.admin-table:not(.ambassador-cards-mobile) > tbody > tr,
    [data-ambassador-detail] table.admin-table:not(.ambassador-cards-mobile) > tbody > tr > td {
        display: block;
        width: 100%;
        max-width: 100%;
        min-width: 0;
        box-sizing: border-box;
        white-space: normal;
        overflow-wrap: anywhere;
        word-break: break-word;
    }
    [data-ambassador-detail] table.admin-table:not(.ambassador-cards-mobile) > thead {
        display: none;
    }
    /* La derniere cellule (boutons/PDF) de ces tables stackees occupe la
       pleine largeur et s'aligne a gauche au lieu de text-align:right. */
    [data-ambassador-detail] table.admin-table:not(.ambassador-cards-mobile) > tbody > tr > td {
        text-align: left;
    }

    /* (c) Les cellules des tables-cartes coupent les valeurs longues
           (codes, e-mail, IBAN, n. de suivi, references, methode de
           versement) au lieu de les laisser pousser la largeur. */
    [data-ambassador-detail] table.ambassador-cards-mobile td {
        overflow-wrap: anywhere;
        word-break: break-word;
        min-width: 0;
    }
    [data-ambassador-detail] table.ambassador-cards-mobile code,
    [data-ambassador-detail] table.ambassador-cards-mobile .ambassador-code-pill,
    [data-ambassador-detail] table.ambassador-cards-mobile .detail-mono,
    [data-ambassador-detail] table.ambassador-cards-mobile .ambassador-compta__method-with-ref,
    [data-ambassador-detail] table.ambassador-cards-mobile a {
        white-space: normal;
        overflow-wrap: anywhere;
        word-break: break-word;
        min-width: 0;
        max-width: 100%;
    }

    /* (e) Le gabarit carte de base met le <td> en flex (label ::before +
           valeur côte à côte, gap:16px, justify:space-between). Une valeur
           dont la largeur minimale de contenu dépasse l'espace disponible
           (cellule Méthode : libellé + valeur + gap) ne peut pas rétrécir et
           déborde (scrollWidth 369 > 299) malgré white-space:normal. On
           repasse ces cellules en bloc dans la fiche : le libellé ::before
           devient un bloc au-dessus de la valeur, ce qui supprime la
           contrainte de largeur minimale du flex et le dernier débordement. */
    [data-ambassador-detail] table.ambassador-cards-mobile td {
        display: block;
        text-align: left;
    }
    [data-ambassador-detail] table.ambassador-cards-mobile td::before {
        display: block;
        min-width: 0;
        overflow-wrap: anywhere;
    }

    /* (f) Les cellules des tables de la fiche heritent white-space:nowrap de
           plusieurs regles de base DUPLIQUEES et tres specifiques
           (.ambassador-detail__payouts-table th/td {nowrap} x4, plus
           body.admin .admin-table td {nowrap} dans @media 768px, plus les
           classes de colonne .ambassador-compta__col-*). En vue carte cela
           empeche la valeur de revenir a la ligne → debordement residuel
           (cellule Methode 369px, code ambassadeur 306px). La bataille de
           specificite contre 4+ regles dupliquees etant non fiable, on force
           ici le retour a la ligne avec !important, strictement limite aux
           cellules des tables de la fiche en vue mobile. */
    [data-ambassador-detail] table.admin-table td,
    [data-ambassador-detail] table.admin-table th {
        white-space: normal !important;
        overflow-wrap: anywhere;
        word-break: break-word;
    }

    /* (d) Les conteneurs flex d'actions / d'icones passent a la ligne
           au lieu de rester en nowrap et de pousser la largeur. */
    [data-ambassador-detail] .ambassador-detail__codes-actions,
    [data-ambassador-detail] .ambassador-compta__doc-icons {
        flex-wrap: wrap;
        max-width: 100%;
        min-width: 0;
    }
}

/* === Nav "Réglages" dropdown group =======================================
 * Desktop: the group is a relative anchor; its submenu is absolutely
 * positioned below the trigger button and hidden until the group is open
 * (.is-open posted by JS, with :focus-within as a keyboard/no-JS fallback).
 * The trigger button mimics the look of the sibling .admin-nav links.
 * Mobile (≤768px, inside the collapsed burger menu): see the media query at
 * the bottom — the submenu renders inline and static (Option A). */
.admin-nav__group { position: relative; display: inline-flex; }
.admin-nav__group-btn {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .5rem .9rem;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: .9rem;
    opacity: .85;
    cursor: pointer;
    transition: background var(--transition), opacity var(--transition), color var(--transition);
}
.admin-nav__group-btn:hover {
    opacity: 1;
    background: rgba(248, 244, 236, .08);
    color: var(--bg);
}
.admin-nav__group-btn[aria-current="page"] {
    color: var(--primary-dark); background: var(--accent);
    opacity: 1; font-weight: 600;
}
.admin-nav__caret {
    font-size: .7em; line-height: 1;
    transition: transform var(--transition);
}
.admin-nav__group.is-open .admin-nav__caret { transform: rotate(180deg); }

.admin-nav__submenu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 180px;
    display: none;
    flex-direction: column;
    gap: .1rem;
    padding: .35rem;
    background: var(--surface, #fff);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
    z-index: 60;
}
.admin-nav__group.is-open .admin-nav__submenu,
.admin-nav__group:focus-within .admin-nav__submenu { display: flex; }
.admin-nav__submenu a {
    display: block;
    padding: .5rem .7rem;
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: .9rem;
    opacity: 1;
    white-space: nowrap;
    transition: background var(--transition), color var(--transition);
}
.admin-nav__submenu a:hover {
    background: var(--accent);
    color: var(--primary-dark);
}
.admin-nav__submenu a[aria-current="page"] {
    background: var(--accent);
    color: var(--primary-dark);
    font-weight: 600;
}
/* The inline "Réglages" subheading is only shown in the mobile inline layout. */
.admin-nav__subhead { display: none; }

@media (max-width: 768px) {
    /* OPTION A — inside the collapsed burger menu, the dropdown becomes a
     * static, always-visible inline group: no positioning, no JS needed. */
    body.admin .amb-menu .admin-nav__group {
        display: flex;
        flex-direction: column;
        width: 100%;
    }
    body.admin .amb-menu .admin-nav__group-btn {
        display: none; /* the trigger is replaced by a static subheading */
    }
    body.admin .amb-menu .admin-nav__submenu {
        position: static;
        display: flex;
        min-width: 0;
        padding: 0;
        background: transparent;
        border: 0;
        box-shadow: none;
        gap: .15rem;
    }
    body.admin .amb-menu .admin-nav__subhead {
        display: block;
        padding: .55rem .9rem .25rem;
        font-size: .72rem;
        font-weight: 700;
        letter-spacing: .06em;
        text-transform: uppercase;
        opacity: .6;
    }
    body.admin .amb-menu .admin-nav__submenu a {
        padding: .7rem .9rem .7rem 1.5rem; /* indent the grouped items */
        font-size: .95rem;
        color: var(--accent);
    }
    body.admin .amb-menu .admin-nav__submenu a:hover,
    body.admin .amb-menu .admin-nav__submenu a[aria-current="page"] {
        background: var(--accent);
        color: var(--primary-dark);
    }
}
