:root {
    --bleu: #3056D3;
    --ardoise: #0F1B2D;
    --sarcelle: #14B8A6;
    --ambre: #E8642A;
    --brume: #EEF2FF;
    --slate: #475467;
    --nuage: #F8FAFC;
    --blanc: #FFFFFF;
    --ligne: #E2E8F0;
}

body {
    background-color: var(--nuage);
    color: var(--ardoise);
    font-family: 'Inter', system-ui, sans-serif;
}

h1, h2, h3, h4, .navbar-brand, .stat-value, .price-hero {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    letter-spacing: -0.02em;
}

/* Raccourci backend, rendu seulement pour un utilisateur interne connecté
   (cus.admin_banner). Ardoise foncée : il doit se lire comme un outil, pas
   concurrencer l'orange du bandeau chantier juste en dessous. */
.admin-banner {
    background: var(--ardoise);
    color: #fff;
    font-size: .88rem;
    line-height: 1.4;
    padding: 7px 16px;
}

.admin-banner a {
    color: #5df0e0;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    margin-left: 8px;
}

.admin-banner a:hover {
    color: #fff;
}

/* Construction notice. Deliberately loud — the site is public only so it can
   be shared with a handful of people, and a visitor has to understand that
   before reading a single price. The orange is the brand's Ambre Alerte
   darkened to #B8481A: the palette value (#E8642A) puts white text at ~3.4:1,
   under the 4.5:1 a paragraph needs. */
.project-banner {
    background: #B8481A;
    color: #fff;
    font-size: .92rem;
    line-height: 1.5;
    padding: 14px 16px;
    border-bottom: 4px solid #8A340F;
}

.project-banner-title {
    display: block;
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 700;
    font-size: 1.15rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    margin-bottom: 2px;
}

.project-banner-text {
    display: block;
    max-width: 60rem;
    margin: 0 auto;
    opacity: .95;
}

/* Policy pages reuse .about-prose; only the date line is theirs. */
.legal-updated {
    font-size: .85rem;
    color: var(--slate);
    margin-top: 6px;
    margin-bottom: 0;
}

.project-banner-contact {
    display: block;
    margin-top: 4px;
}

.project-banner-contact a {
    color: #fff;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    /* An address is a single long token: let it wrap rather than push the
       banner into a horizontal scroll on a narrow phone. */
    word-break: break-word;
}

.project-banner-contact a:hover {
    color: #FFE3D3;
}

@media (max-width: 575.98px) {
    .project-banner { font-size: .85rem; padding: 12px 14px; }
    .project-banner-title { font-size: 1rem; }
}

.navbar-brand {
    font-weight: 700;
    color: var(--ardoise) !important;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* The links beside the brand. `navbar-expand-md` on the <nav> looks like it
   handles this and does not: Bootstrap's JS is not loaded here and there is no
   toggler, so the class collapses nothing and the links stay in a flex row
   that cannot wrap. Measured 2026-07-29 at a 420 px viewport: the row was
   594 px wide, so `documentElement.scrollWidth` was 606 against a 420 px
   client width — the whole site scrolled sideways, on every page, with a white
   gutter down the right of anything screenshotted.

   Wrapping is the fix rather than a hamburger because a hamburger needs
   JavaScript on pages that load none: the member area's shell pulls in only
   its own two scripts, so a toggler there would be a button that does nothing. */
.navbar-links {
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: 2px;
    /* Without this the flex item refuses to shrink below its content width,
       which is the overflow itself: it wraps the row but keeps the box wide. */
    min-width: 0;
}

/* Wrap the row, never a link's own words — "Produits généraux" broken across
   two lines is what made the bar three rows deep before it overflowed anyway. */
.navbar-links .btn-link {
    white-space: nowrap;
}

@media (max-width: 767.98px) {
    .navbar-links .btn-link {
        padding-left: 0.4rem;
        padding-right: 0.4rem;
        font-size: 0.92rem;
    }

    .navbar-brand {
        font-size: 1.05rem;
    }
}

.navbar-brand .le {
    font-weight: 500;
    opacity: .75;
}

.brand-mark {
    width: 34px;
    height: 34px;
    border-radius: 9px;
    background: var(--bleu);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.brand-mark svg {
    width: 20px;
    height: 20px;
}

.eyebrow {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #8fe9dd;
    display: inline-block;
}

.hero {
    background: linear-gradient(155deg, #0F1B2D 0%, #16305c 66%, #3056D3 175%);
    color: #fff;
    padding: 72px 0 64px;
}

.hero h1 {
    font-size: 2.4rem;
    font-weight: 700;
    margin-top: 14px;
    margin-bottom: .75rem;
}

.hero p.lead {
    font-size: 1.15rem;
    color: #c3d2ec;
    max-width: 640px;
    margin: 0 auto;
}

.hero-search {
    max-width: 560px;
    margin: 28px auto 0;
}

.hero-search .form-control {
    border-radius: 50px 0 0 50px;
    border: none;
    padding: 14px 20px;
}

.hero-search .btn {
    border-radius: 0 50px 50px 0;
    padding: 0 28px;
    background: var(--sarcelle);
    border: none;
    color: var(--ardoise);
    font-weight: 600;
}

/* The second way into the catalogue, under the hero's search box. Teal rather
   than white because it is the alternative to the button above it, not a rival
   to it — the same #8fe9dd the eyebrow already carries on this gradient. */
.hero-alt {
    font-size: .95rem;
    color: #c3d2ec;
}

.hero-alt a {
    color: #8fe9dd;
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid rgba(143, 233, 221, .45);
}

.hero-alt a:hover {
    color: #fff;
    border-bottom-color: #fff;
}

.stats-bar {
    background: white;
    border-bottom: 1px solid var(--ligne);
}

.stats-bar .stat-value {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--bleu);
}

.stats-bar .stat-label {
    font-size: .8rem;
    color: var(--slate);
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* Banner tile on the home page. Deliberately not a card: no box, no border,
   no hover lift. Product lists on this site are tables, and a row of framed
   boxes above them read as the page's main object when it is the tables. */
.retailer-tile {
    display: block;
    text-align: center;
    padding: 8px 4px;
    transition: opacity .2s;
}

.retailer-tile:hover {
    opacity: .7;
}

.retailer-logo {
    height: 48px;
    max-width: 110px;
    object-fit: contain;
    margin-bottom: 10px;
}

.retailer-tile h5 {
    font-weight: 600;
    margin-bottom: 2px;
    color: var(--ardoise);
}

/* Product page gallery: one large image, the alternatives under it. */
.product-gallery-main {
    width: 100%;
    max-height: 340px;
    object-fit: contain;
    border: 1px solid var(--ligne);
    border-radius: 16px;
    background: white;
    padding: 12px;
}

.product-gallery-thumbs {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    flex-wrap: wrap;
}

.product-gallery-thumb {
    width: 64px;
    height: 64px;
    padding: 4px;
    background: white;
    border: 1px solid var(--ligne);
    border-radius: 10px;
    cursor: pointer;
}

.product-gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* The selected thumbnail, marked by the same blue the prices use rather than
   by a shadow — a thumbnail is small enough that a border is the only change
   readable at that size. */
.product-gallery-thumb.active {
    border-color: var(--bleu);
    border-width: 2px;
    padding: 3px;
}

.price-hero {
    color: var(--bleu);
}

/* The unit the comparable price refers to ("/L"), kept smaller than the figure
   itself so the hero reads as one price rather than two. */
.price-hero small {
    font-size: .55em;
    font-weight: 600;
    color: var(--slate);
}

/* Product name cell of any product table: thumbnail beside the name rather
   than in a column of its own — most products have no photo, and a column
   would be a stripe of blank running down the table. */
.price-table .product-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.price-table .product-row-thumb {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    object-fit: contain;
}

/* The out-link to the retailer's own page, beside the banner name. Faded until
   hovered: it repeats on every row, and at full strength a column of icons
   competes with the figures the table exists to show. */
.price-table .retailer-link {
    color: var(--slate);
    opacity: .45;
}

.price-table .retailer-link:hover {
    opacity: 1;
    color: var(--bleu);
}

/* The column meant to be scanned down, so not muted like its neighbours. */
.price-table .comparison-cell {
    font-weight: 600;
    font-size: .85rem;
    color: var(--bleu);
    white-space: nowrap;
}

.badge-brand {
    font-size: .7rem;
    align-self: flex-start;
    background: var(--brume);
    color: var(--ardoise);
    font-weight: 600;
}

.filter-pill {
    border-radius: 50px;
    padding: 6px 16px;
    font-size: .85rem;
    border: 1px solid var(--ligne);
    background: white;
    color: var(--slate);
    text-decoration: none;
    display: inline-block;
    margin: 0 6px 8px 0;
}

.filter-pill.active,
.filter-pill:hover {
    background: var(--bleu);
    color: white;
    border-color: var(--bleu);
}

/* --- /explorer -----------------------------------------------------------
   The page is four stacked rows of pills, so what keeps it readable is the
   labelling between them rather than the pills themselves, which are the
   ordinary .filter-pill everywhere else on the site uses. */
.facet-block {
    margin-bottom: 18px;
}

.facet-block:last-child {
    margin-bottom: 0;
}

.facet-label {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ardoise);
    margin-bottom: 8px;
}

/* One step quieter than .facet-label: a facet name sits *inside* the Affiner
   block, and giving the two the same weight would read as eleven sections
   rather than one with eleven rows. */
.facet-sublabel {
    font-size: .8rem;
    font-weight: 600;
    color: var(--slate);
    margin-bottom: 6px;
}

.facet-hint {
    font-family: 'Inter', system-ui, sans-serif;
    font-size: .78rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--slate);
    margin-left: 10px;
}

/* The count is the whole point of the pill — it is what orders the list — but
   it is not what you read first, so it trails the label a shade back. */
.filter-count {
    margin-left: 6px;
    font-size: .75rem;
    color: var(--slate);
    font-variant-numeric: tabular-nums;
}

.filter-pill.active .filter-count,
.filter-pill:hover .filter-count {
    color: #d7e0ff;
}

.explorer-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}

.explorer-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 50px;
    padding: 3px 10px;
    font-size: .78rem;
    background: var(--brume);
    color: var(--bleu);
    border: 1px solid transparent;
    text-decoration: none;
}

.explorer-chip:hover {
    background: var(--bleu);
    color: white;
}

.explorer-chip-x {
    font-size: .9rem;
    line-height: 1;
}

.explorer-chip-reset {
    font-size: .78rem;
    color: var(--slate);
    text-decoration: underline;
}

.price-hero {
    font-size: 2.2rem;
    font-weight: 700;
}

.btn-primary {
    background: var(--bleu);
    border-color: var(--bleu);
}

.btn-primary:hover {
    background: #2745b0;
    border-color: #2745b0;
}


footer {
    background: var(--ardoise);
    color: #c3d2ec;
    padding: 32px 0;
    font-size: .9rem;
}

footer strong {
    color: #fff;
    font-family: 'Space Grotesk', sans-serif;
}

footer a {
    color: #c3d2ec;
}

.backend-link {
    display: inline-block;
    margin-top: 10px;
    font-size: .7rem;
    opacity: .35;
    text-decoration: none;
}

.backend-link:hover {
    opacity: .7;
}

.empty-state {
    padding: 60px 20px;
    text-align: center;
    color: var(--slate);
}

.lang-toggle {
    margin-left: 8px;
    font-size: .8rem;
    font-weight: 600;
    color: var(--slate);
}

.lang-toggle .lang-link {
    color: var(--slate);
    text-decoration: none;
    padding: 2px 4px;
}

.lang-toggle .lang-link.active {
    color: var(--bleu);
}

.lang-toggle .lang-sep {
    opacity: .5;
}

/* --- Tableaux de prix : listes larges, colonnes de prix -------------- */

/* The wrapper scrolls, not the page body: on a phone the price columns stay
   reachable by scrolling sideways while the product column stays pinned. */
.price-table-wrap {
    max-height: 78vh;
    overflow: auto;
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 10px;
}

.price-table {
    font-size: .85rem;
    margin-bottom: 0;
}

.price-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--brume);
    color: var(--ardoise);
    font-weight: 600;
    white-space: nowrap;
    border-bottom: 1px solid var(--ligne);
}

.price-table td.col-product,
.price-table thead th.col-product {
    position: sticky;
    left: 0;
    background: var(--blanc);
    min-width: 240px;
}

.price-table thead th.col-product {
    z-index: 3;
    background: var(--brume);
}

.price-table tbody tr:hover td {
    background: var(--nuage);
}

.price-table .price-cell {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    white-space: nowrap;
}

/* nowrap or the ISO date breaks after the month ("2026-07-" / "18") — the
   price columns are narrow enough that the browser will take the offer. */
.price-table .price-cell-date {
    font-size: .72rem;
    white-space: nowrap;
}

.price-table td {
    vertical-align: middle;
}

/* Le sens des couleurs — l'ambre pour un prix qui monte, la sarcelle pour un
   prix qui baisse — vaut partout où une variation s'imprime, pas seulement
   dans un tableau : la fiche produit en écrit une en toutes lettres. Le
   curseur d'aide reste au tableau, lui, parce qu'il appartient à une cellule
   serrée dont le détail vit dans une infobulle. */
.trend-up {
    color: var(--ambre);
}

.trend-down {
    color: var(--sarcelle);
}

/* L'écart est la raison d'être de la colonne — c'est lui qu'on lit, pas le
   taux qu'il annote. Il était écrit plus petit que la mention de succursale
   à côté ; il est maintenant à peine sous le corps du tableau. */
.price-table .trend {
    font-size: .9rem;
    cursor: help;
}

/* --- Page à propos : colonne de lecture sobre, sans cartes ni ornements --- */

.about-page {
    background: var(--blanc);
    padding: 64px 0 80px;
    border-top: 1px solid var(--ligne);
}

.about-prose {
    max-width: 42rem;
    margin: 0 auto;
}

.about-prose h1 {
    font-size: 2.1rem;
    margin: 6px 0 0;
}

.about-prose h2 {
    font-size: 1.15rem;
    margin: 42px 0 12px;
    color: var(--ardoise);
}

.about-prose p,
.about-prose li {
    color: var(--slate);
    line-height: 1.75;
}

.about-prose p {
    margin-bottom: 1rem;
}

.about-prose .about-intro {
    font-size: 1.1rem;
    color: var(--ardoise);
    margin-top: 20px;
    padding-bottom: 8px;
}

.about-prose ul {
    padding-left: 1.1rem;
    margin-bottom: 1rem;
}

.about-prose li {
    margin-bottom: .5rem;
}

.about-prose h3 {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ardoise);
    margin-bottom: 4px;
}

/* --- Principes du registre : deux règles numérotées dans la colonne de lecture --- */

.principle {
    display: flex;
    gap: 16px;
    padding: 14px 0;
    border-top: 1px solid var(--ligne);
}

.principle:last-of-type {
    border-bottom: 1px solid var(--ligne);
}

.principle-num {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-weight: 700;
    font-size: 1.3rem;
    color: var(--bleu);
    line-height: 1.3;
    flex-shrink: 0;
    width: 34px;
}

.principle p {
    margin-bottom: 0;
}

/* --- Page détaillants : une enseigne par bloc, logo + description --- */

.retailer-block {
    padding: 26px 0;
    border-bottom: 1px solid var(--ligne);
}

.retailer-block-head {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 12px;
}

.retailer-block-logo {
    height: 40px;
    max-width: 96px;
    object-fit: contain;
    flex-shrink: 0;
}

.retailer-block h3 {
    font-size: 1.15rem;
    margin-bottom: 2px;
}

.retailer-kind {
    font-size: .9rem;
    color: var(--bleu);
    font-weight: 600;
}

.retailer-owner {
    font-size: .8rem;
    color: var(--slate);
}

.retailer-figures {
    display: flex;
    flex-wrap: wrap;
    gap: 18px;
    font-size: .85rem;
    color: var(--slate);
}

.retailer-figures strong {
    color: var(--ardoise);
    margin-right: 4px;
}

.retailer-note {
    margin-top: 28px;
    font-size: .85rem;
    color: var(--slate);
    opacity: .85;
}

@media (max-width: 575.98px) {
    .about-page { padding: 40px 0 56px; }
    .about-prose h1 { font-size: 1.7rem; }
    .principle { gap: 10px; }
    .principle-num { width: 26px; font-size: 1.1rem; }
    .retailer-block-head { gap: 12px; }
}

/* --- /produits-generaux : one item, every banner ------------------------- */

.generic-intro {
    max-width: 46rem;
}

/* The one sentence that carries the page's point — how far apart the same
   item is priced — so it is set apart from the surrounding muted text. */
.generic-spread {
    background: var(--brume);
    border-left: 4px solid var(--bleu);
    border-radius: 0 10px 10px 0;
    padding: 12px 16px;
    margin-top: 18px;
    color: var(--ardoise);
    max-width: 46rem;
}

/* The comparison table's product column: wide enough not to wrap every name,
   but NOT sticky like .col-product — here it is the second column,
   and pinning it to the left edge would slide it under the banner column. */
.offer-product {
    min-width: 220px;
}

.price-table tbody tr.offer-best td {
    background: rgba(20, 184, 166, .08);
}

.price-table tbody tr.offer-best:hover td {
    background: rgba(20, 184, 166, .14);
}

/* ===================================================================
   L'espace membre (/mon-espace, /ma-liste, /mes-achats, /mes-preuves).
   Same palette and the same tables as the public pages — a member is on
   the same site, and a portal styled as a separate application is how
   two designs end up drifting apart. What is genuinely new here is the
   tab strip, the stat blocks and the proof cards.
   =================================================================== */

/* The tab strip sits directly under the navbar and reads as an extension
   of it, so it takes the navbar's white and its bottom rule rather than
   introducing a third surface. */
.member-bar {
    background: var(--blanc);
    border-bottom: 1px solid var(--ligne);
}

.member-bar .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.member-tabs {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.member-tab {
    display: inline-block;
    padding: 12px 14px;
    color: var(--slate);
    text-decoration: none;
    font-size: 0.94rem;
    font-weight: 500;
    /* Transparent rather than absent: the active tab's rule must not shift
       the row of labels down by two pixels when it appears. */
    border-bottom: 2px solid transparent;
}

.member-tab:hover {
    color: var(--bleu);
}

.member-tab.active {
    color: var(--bleu);
    border-bottom-color: var(--bleu);
}

.member-who {
    color: var(--slate);
    font-size: 0.88rem;
}

.member-page {
    padding: 40px 0 72px;
}

.member-h1 {
    font-size: 1.9rem;
    margin-bottom: 6px;
}

.member-lead {
    max-width: 46rem;
    margin-bottom: 28px;
}

.member-narrow {
    max-width: 42rem;
}

.member-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 28px;
}

.member-stat {
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 12px;
    padding: 16px 20px;
    min-width: 13rem;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.member-stat-value {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    font-size: 1.6rem;
    font-weight: 600;
    color: var(--ardoise);
}

.member-stat-label {
    font-size: 0.85rem;
    color: var(--slate);
}

.member-stat-hint {
    font-size: 0.76rem;
    color: var(--slate);
    opacity: 0.8;
}

.member-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    gap: 18px;
}

.member-card {
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 14px;
    padding: 20px 22px;
}

.member-card h2 {
    font-size: 1.05rem;
    margin-bottom: 12px;
}

.member-plain-list {
    list-style: none;
    padding: 0;
    margin: 0 0 14px;
}

.member-plain-list li {
    padding: 5px 0;
    border-bottom: 1px solid var(--ligne);
    font-size: 0.92rem;
}

.member-plain-list li:last-child {
    border-bottom: 0;
}

/* --- Forms ------------------------------------------------------- */

.member-add-form {
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 14px;
    padding: 20px 22px;
    margin-bottom: 28px;
}

.member-form-h2 {
    font-size: 1.05rem;
    margin-bottom: 14px;
}

/* Two columns on a desktop, one on a phone. The wide fields span both, which
   is what keeps a product name from sharing a row with a quantity. */
.member-field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 14px;
}

.member-field-wide {
    grid-column: 1 / -1;
}

/* --- The grocery list --------------------------------------------- */

/* Sized for one thumb on a phone in a store aisle, which is the only place
   this page is really used: nothing interactive is under 40 px, the tick and
   the quantity stepper sit at opposite ends of the row so neither is hit by
   accident, and the whole list is one column at every width — two columns of
   groceries would be read as two lists. */

.list-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

/* The title has to be allowed to shrink, or it takes the whole row and pushes
   the estimate onto a line of its own where a right-aligned block sitting at
   flex-start reads as centred — which is exactly how it looked. */
.list-head-title {
    flex: 1 1 20rem;
    min-width: 0;
}

.list-estimate {
    flex: 0 0 auto;
    text-align: right;
    max-width: 22rem;
}

/* Wrapped onto its own line there is nothing to align against, so the figure
   goes back to the left margin with everything else rather than floating. */
@media (max-width: 575.98px) {
    .list-estimate {
        width: 100%;
        max-width: none;
        text-align: left;
    }
}

.list-estimate-empty {
    display: none;
}

.list-estimate-figure {
    display: block;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--ardoise);
    line-height: 1.1;
}

.list-estimate-note {
    display: block;
    font-size: 0.76rem;
    color: var(--slate);
    margin-top: 4px;
}

/* Deliberately not sticky. It was, on the theory that adding an item should
   always be one tap away; in a browser it turned into an opaque bar sliding
   over the items and their offers, and the aisle gesture this page exists for
   is ticking things off, not adding them. */
.list-add {
    display: flex;
    gap: 10px;
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 14px;
    padding: 12px;
    margin-bottom: 26px;
}

.list-add-input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    background: transparent;
    font-size: 1rem;
    padding: 10px 8px;
}

.list-add-input:focus {
    outline: 0;
}

.list-add-submit {
    flex: 0 0 auto;
    border: 0;
    border-radius: 9px;
    background: var(--sarcelle);
    color: #fff;
    font-size: 0.9rem;
    font-weight: 600;
    padding: 10px 18px;
    cursor: pointer;
}

.list-section-h2 {
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--slate);
    margin: 26px 0 10px;
}

.list-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.list-section-head .list-section-h2 {
    margin-bottom: 10px;
}

.list-items {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--ligne);
    border-radius: 14px;
    background: var(--blanc);
    overflow: hidden;
}

.list-item {
    display: flex;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--ligne);
}

.list-item:last-child {
    border-bottom: 0;
}

/* A ticked item is struck through and faded rather than hidden: the point of
   ticking it in the aisle is to see that it is done, and an item that vanishes
   cannot be un-ticked by someone who tapped the wrong row. */
.list-item-done .list-item-label {
    text-decoration: line-through;
}

.list-item-done {
    opacity: 0.55;
}

.list-item-body {
    flex: 1 1 auto;
    min-width: 0;
}

.list-item-top {
    display: flex;
    align-items: center;
    gap: 10px;
}

.list-item-label {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 500;
    overflow-wrap: anywhere;
}

.list-check {
    flex: 0 0 auto;
    width: 1.6rem;
    height: 1.6rem;
    margin-top: 2px;
    border: 1.5px solid var(--ligne);
    border-radius: 6px;
    background: var(--blanc);
    color: var(--sarcelle);
    font-size: 0.95rem;
    line-height: 1;
    padding: 0;
    cursor: pointer;
}

.list-check:hover {
    border-color: var(--sarcelle);
}

.list-qty {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 2px;
}

.list-qty-step {
    width: 1.8rem;
    height: 1.8rem;
    border: 1px solid var(--ligne);
    border-radius: 6px;
    background: var(--blanc);
    color: var(--ardoise);
    font-size: 1rem;
    line-height: 1;
    padding: 0;
    cursor: pointer;
}

.list-qty-value {
    min-width: 1.6rem;
    text-align: center;
    font-size: 0.9rem;
    color: var(--slate);
}

.list-drop {
    border: 0;
    background: transparent;
    color: var(--slate);
    font-size: 1.15rem;
    line-height: 1;
    padding: 4px 6px;
    cursor: pointer;
}

.list-drop:hover {
    color: var(--ardoise);
}

/* The clipped offer: the banner, then the product, then what it costs. The
   banner comes first because it is the part that changes what the member
   does. */
.list-item-clip {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 4px;
    font-size: 0.84rem;
}

.list-clip-brand {
    font-weight: 600;
    color: var(--sarcelle);
}

.list-clip-name {
    color: var(--slate);
    overflow-wrap: anywhere;
}

.list-clip-price {
    font-weight: 600;
    color: var(--ardoise);
}

.list-clip-undo {
    border: 0;
    background: transparent;
    color: var(--slate);
    font-size: 0.78rem;
    text-decoration: underline;
    padding: 0;
    cursor: pointer;
}

.list-offers-link {
    display: inline-block;
    margin-top: 6px;
    font-size: 0.8rem;
    color: var(--sarcelle);
    cursor: pointer;
}

.list-offers-link-empty {
    color: var(--slate);
}

.list-offers-loading {
    color: var(--slate);
    font-size: 0.8rem;
    margin: 8px 0 0;
}

/* --- The offers under an item ------------------------------------- */

.list-offers {
    margin-top: 8px;
}

.list-offers-head,
.list-offers-none {
    font-size: 0.78rem;
    color: var(--slate);
    margin: 0 0 6px;
}

.list-offer-set {
    list-style: none;
    margin: 0;
    padding: 0;
}

.list-offer {
    display: flex;
    align-items: stretch;
    gap: 6px;
    margin-bottom: 6px;
}

.list-offer-form {
    flex: 1 1 auto;
    min-width: 0;
}

/* The whole card is the button. Picking an offer is the one thing this panel
   is for, and a row with a small "choose" link at the end of it invites
   reading before deciding — the price is already the decision. */
.list-offer-pick {
    display: flex;
    width: 100%;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    text-align: left;
    border: 1px solid var(--ligne);
    border-radius: 10px;
    background: var(--blanc);
    padding: 8px 12px;
    cursor: pointer;
}

.list-offer-pick:hover {
    border-color: var(--sarcelle);
}

.list-offer-chosen .list-offer-pick {
    border-color: var(--sarcelle);
    box-shadow: inset 0 0 0 1px var(--sarcelle);
}

.list-offer-left {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.list-offer-brand {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--sarcelle);
}

.list-offer-name {
    font-size: 0.86rem;
    color: var(--ardoise);
    overflow-wrap: anywhere;
}

.list-offer-meta {
    font-size: 0.75rem;
    color: var(--slate);
}

/* An advertised price expires; a shelf reading does not. The badge is the
   only thing on the card that says which of the two a member is reading. */
.list-offer-flyer {
    align-self: flex-start;
    margin-top: 3px;
    font-size: 0.7rem;
    font-weight: 600;
    color: #8a5a00;
    background: #fff3d6;
    border-radius: 4px;
    padding: 1px 6px;
}

.list-offer-right {
    flex: 0 0 auto;
    text-align: right;
}

.list-offer-price {
    display: block;
    font-size: 1rem;
    font-weight: 600;
    color: var(--ardoise);
}

.list-offer-verb {
    display: block;
    font-size: 0.72rem;
    color: var(--sarcelle);
}

.list-offer-sheet {
    flex: 0 0 auto;
    align-self: center;
    font-size: 0.72rem;
    color: var(--slate);
    padding: 0 4px;
}

/* --- The list read as an itinerary -------------------------------- */

.list-stores {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 12px;
}

.list-store {
    border: 1px solid var(--ligne);
    border-radius: 12px;
    background: var(--blanc);
    padding: 12px 14px;
}

.list-store-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.list-store-name {
    font-weight: 600;
    color: var(--sarcelle);
}

.list-store-total {
    font-weight: 600;
    color: var(--ardoise);
}

.list-store-items {
    margin: 6px 0 0;
    font-size: 0.82rem;
    color: var(--slate);
}

.list-admin {
    margin-top: 30px;
    font-size: 0.85rem;
    color: var(--slate);
}

.list-admin summary {
    cursor: pointer;
}

.list-admin-body {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-top: 12px;
}

.list-admin-form {
    display: flex;
    align-items: center;
    gap: 6px;
}

.list-admin-form .form-control,
.list-admin-form .form-select {
    width: 11rem;
}

/* --- Purchases ---------------------------------------------------- */

.member-day {
    margin-bottom: 22px;
}

.member-day-head {
    display: flex;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    padding: 0 4px 6px;
    font-size: 0.9rem;
    color: var(--slate);
}

.member-day-date {
    font-weight: 600;
    color: var(--ardoise);
}

.member-day-total {
    margin-left: auto;
}

.member-row-actions form {
    display: inline;
}

/* --- Proofs -------------------------------------------------------- */

.member-proof {
    display: flex;
    gap: 18px;
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 14px;
    padding: 18px 20px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}

.member-proof-body {
    flex: 1 1 20rem;
}

.member-proof-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.member-proof-figures {
    font-size: 0.95rem;
}

.member-proof-thumbs {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.member-proof-thumbs img {
    width: 92px;
    height: 92px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--ligne);
}

.member-badge {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.member-badge-submitted {
    background: var(--brume);
    color: var(--bleu);
}

.member-badge-accepted {
    background: rgba(20, 184, 166, .14);
    color: #0F766E;
}

.member-badge-rejected {
    background: rgba(184, 72, 26, .12);
    color: #B8481A;
}

.member-review-note {
    background: var(--nuage);
    border-left: 3px solid var(--ligne);
    border-radius: 0 8px 8px 0;
    padding: 8px 12px;
    margin-top: 10px;
    font-size: 0.86rem;
    color: var(--slate);
}

/* --- The product picker ------------------------------------------- */

.product-picker {
    position: relative;
}

.product-picker-results {
    position: absolute;
    z-index: 20;
    left: 0;
    right: 0;
    background: var(--blanc);
    border: 1px solid var(--ligne);
    border-radius: 10px;
    box-shadow: 0 12px 28px rgba(15, 27, 45, .12);
    max-height: 17rem;
    overflow-y: auto;
    margin-top: 4px;
}

.product-picker-item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--ligne);
    padding: 8px 12px;
    font-size: 0.88rem;
    cursor: pointer;
}

.product-picker-item:last-child {
    border-bottom: 0;
}

.product-picker-item:hover {
    background: var(--brume);
}

.product-picker-item-name {
    display: block;
    color: var(--ardoise);
}

.product-picker-item-meta {
    display: block;
    color: var(--slate);
    font-size: 0.78rem;
}

.product-picker-chosen {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--brume);
    border-radius: 8px;
    padding: 7px 12px;
    font-size: 0.88rem;
    color: var(--ardoise);
}

.product-picker-chosen-label {
    flex: 1 1 auto;
}

.product-picker-clear {
    border: 0;
    background: none;
    color: var(--slate);
    font-size: 1.1rem;
    line-height: 1;
    padding: 0 4px;
    cursor: pointer;
}
