
  .cart-bar {
    position: fixed;
    left: 50%;
    bottom: 16px;
    transform: translateX(-50%);
    z-index: 62;
    width: min(560px, calc(100% - 24px));
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 8px 8px 6px;
    border-radius: var(--fichi-radius-full);
    background: var(--fichi-bg-elevated);
    border: 1px solid var(--fichi-border-subtle);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
  }
  .cart-bar[hidden] { display: none !important; }
  /* While the list is up it owns the corner. */
  body:has(.cart-bar:not([hidden])) .wa-fab { display: none; }
  .cart-open {
    display: flex;
    align-items: center;
    gap: 9px;
    flex: 1;
    min-width: 0;
    min-height: 44px;
    padding: 0 12px;
    border: 0;
    background: none;
    border-radius: var(--fichi-radius-full);
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    color: var(--fichi-text-primary);
    cursor: pointer;
    text-align: left;
  }
  .cart-open .cart-n {
    min-width: 24px;
    padding: 2px 8px;
    border-radius: var(--fichi-radius-full);
    background: var(--store-accent);
    color: var(--store-accent-contrast);
    font-size: 13px;
    text-align: center;
  }
  .cart-send {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 18px;
    border-radius: var(--fichi-radius-full);
    background: #25D366;
    color: #06301A;
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
  }
  .cart-panel {
    position: fixed;
    left: 50%;
    bottom: 78px;
    transform: translateX(-50%);
    z-index: 61;
    width: min(560px, calc(100% - 24px));
    max-height: 70dvh;
    display: flex;
    flex-direction: column;
    border-radius: var(--fichi-radius-xl);
    background: var(--fichi-bg-elevated);
    border: 1px solid var(--fichi-border-subtle);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
    overflow: hidden;
  }
  .cart-panel[hidden] { display: none !important; }
  .cart-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 10px 12px 20px;
    border-bottom: 1px solid var(--fichi-border-subtle);
    font-family: var(--fichi-font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--fichi-text-primary);
  }
  .cart-close {
    width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    border: 0; background: none; color: var(--fichi-text-secondary); cursor: pointer;
  }
  .cart-items { list-style: none; margin: 0; padding: 6px 20px; overflow-y: auto; }
  .cart-items li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--fichi-border-subtle);
  }
  .cart-items li:last-child { border-bottom: 0; }
  .cart-items .who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .cart-items .who b { font-size: 14px; font-weight: 600; color: var(--fichi-text-primary); }
  .cart-items .who span { font-size: 13px; color: var(--fichi-text-muted); font-variant-numeric: tabular-nums; }
  .cart-items .qty { display: flex; align-items: center; gap: 2px; }
  .cart-items .qty button {
    width: 34px; height: 34px;
    border-radius: var(--fichi-radius-md);
    border: 1px solid var(--fichi-border-subtle);
    background: var(--fichi-bg-surface);
    color: var(--fichi-text-primary);
    font: inherit; font-size: 16px; font-weight: 700; cursor: pointer;
  }
  .cart-items .qty output { min-width: 30px; text-align: center; font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
  .cart-foot { padding: 14px 20px calc(14px + env(safe-area-inset-bottom)); border-top: 1px solid var(--fichi-border-subtle); }
  .cart-total { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; font-size: 14px; color: var(--fichi-text-secondary); }
  .cart-total strong { font-size: 19px; color: var(--fichi-text-primary); font-variant-numeric: tabular-nums; }
  .cart-foot .cart-send { display: flex; justify-content: center; }
  .cart-notice {
    margin: 0 0 10px;
    padding: 8px 10px;
    border-radius: var(--fichi-radius-md);
    background: var(--fichi-warning-bg);
    color: var(--fichi-warning-text);
    font-size: 12.5px;
    line-height: 1.45;
  }
  .cart-notice[hidden] { display: none !important; }
  .cart-zone { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; font-size: 14px; }
  .cart-zone select {
    min-height: 40px;
    padding: 0 10px;
    border: 1px solid var(--fichi-border-default);
    border-radius: var(--fichi-radius-md);
    background: var(--fichi-bg-page);
    color: var(--fichi-text-primary);
    font: inherit;
    font-size: 14px;
  }
  .cart-ship { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 6px; font-size: 13.5px; color: var(--fichi-text-secondary); }
  /* The UA gives [hidden] display:none from its OWN stylesheet, which any
     author rule outranks — so the line above kept this row on screen while the
     script had marked it hidden, printing a bare "Envío" with no amount above
     every total. Four siblings already carry this guard; this one did not. */
  .cart-ship[hidden] { display: none !important; }
  .cart-address { display: block; margin-bottom: 12px; font-size: 14px; }
  .cart-address[hidden] { display: none !important; }
  .cart-address span { display: block; margin-bottom: 6px; }
  .cart-address textarea {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--fichi-border-default);
    border-radius: var(--fichi-radius-md);
    background: var(--fichi-bg-page);
    color: var(--fichi-text-primary);
    font: inherit;
    font-size: 14px;
    resize: vertical;
  }
  .cart-address textarea::placeholder { color: var(--fichi-text-muted); opacity: 1; }
  @media (max-width: 640px) {
    .cart-bar { bottom: 12px; }
    .cart-panel { bottom: 74px; max-height: 66dvh; }
    .cart-open .cart-word { display: none; }
  }

  .topbar {
    max-width: 640px;
    margin: 0 auto;
    width: calc(100% - var(--store-inset));
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 0 4px;
  }
  .topbar .back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--fichi-radius-full);
    background: var(--fichi-bg-surface);
    border: 1px solid var(--fichi-border-subtle);
    color: var(--fichi-text-primary);
    text-decoration: none;
    box-shadow: var(--fichi-shadow-sm);
    flex-shrink: 0;
  }
  .topbar .store-name {
    font-size: 15px;
    font-weight: 600;
    color: var(--fichi-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .shell {
    max-width: 640px;
    margin: 8px auto 0;
    width: calc(100% - var(--store-inset));
  }
  .gallery .main-wrap {
    /* Named, so the photo is animated on its own rather than dissolved along
       with the rest of the page. Between two colours of one model the layout
       is identical and this only cross-fades the picture in place; between
       pages whose copy is a different length it is what keeps the photo
       anchored while everything around it changes. One per page — the CSS-only
       switcher's other shots are display:none, so they are never captured. */
    view-transition-name: product-photo;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: var(--fichi-bg-surface);
    border: 1px solid var(--fichi-border-subtle);
    border-radius: var(--fichi-radius-2xl);
    box-shadow: var(--fichi-shadow-sm);
  }
  .gallery { position: relative; }
  /* CSS-only image switcher: hidden radios (one per photo, first checked) drive
     which main image shows and which thumbnail is active — no client JS. Kept
     focusable (not display:none) so keyboard users can arrow between photos. */
  .gallery .gsel { position: absolute; top: 0; left: 0; width: 1px; height: 1px; opacity: 0; }
  .gallery .main {
    width: 100%;
    max-width: 360px;
    aspect-ratio: 1;
    object-fit: contain;
    display: none;
  }
  .gallery .placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 1;
    max-width: 360px;
    font-size: 96px;
    font-weight: 700;
    font-family: var(--fichi-font-display);
    color: var(--fichi-text-muted);
    background: var(--fichi-bg-muted);
    border-radius: var(--fichi-radius-xl);
  }
  .thumbs { display: flex; gap: 10px; margin-top: 14px; }
  .thumbs .thumb {
    width: 64px;
    height: 64px;
    border-radius: var(--fichi-radius-md);
    overflow: hidden;
    background: var(--fichi-bg-surface);
    border: 2px solid var(--fichi-border-subtle);
    flex-shrink: 0;
    cursor: pointer;
    transition: border-color 0.12s;
  }
  .thumbs .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .info { margin-top: 24px; }
  .info .brand { margin: 0 0 6px; font-size: 13px; color: var(--fichi-text-muted); }
  .info .brand strong { color: var(--store-accent-text); font-weight: 600; }
  .info .crumbs ol { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 8px; padding: 0; list-style: none; font-size: 13px; color: var(--fichi-text-secondary); }
  .info .crumbs li > span { margin-right: 4px; }
  .info .crumbs a { color: var(--fichi-text-secondary); text-underline-offset: 3px; }
  .info h1 {
    margin: 0;
    font-family: var(--fichi-font-display);
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.4px;
    line-height: 1.25;
  }
  .info .price {
    margin: 14px 0 0;
    font-size: 26px;
    font-weight: 700;
    color: var(--fichi-text-primary);
    font-variant-numeric: tabular-nums;
  }
  .info .desc-head {
    margin: 26px 0 10px;
    font-family: var(--fichi-font-display);
    font-size: 16px;
    font-weight: 600;
  }
  .info .description {
    margin: 0;
    font-size: 15px;
    line-height: 1.7;
    color: var(--fichi-text-secondary);
    white-space: pre-line;
  }
  /* Colour picker. The current one is a <span>, not a dead link to the page it
     is already on — so a keyboard lands only on the colours it can go to. */
  .info .swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .info .swatch {
    display: inline-block;
    padding: 8px 14px;
    border: 1px solid var(--fichi-border-default);
    border-radius: var(--fichi-radius-full);
    font-size: 14px;
    font-weight: 600;
    color: var(--fichi-text-secondary);
    text-decoration: none;
    transition: border-color 140ms, color 140ms;
  }
  .info a.swatch:hover { border-color: var(--store-accent); color: var(--fichi-text-primary); }
  /* With photos the chip becomes a picture and a name. A colour NAME is a word
     the shop typed — "Carey", "Arena", "Palo de rosa" — and only the shop knows
     what it looks like. The photo of that colour's own product is the one thing
     Rachi has that does: no hex is stored per variant, and inventing one from
     the name would be a guess printed as a fact.
     All or nothing across the row: one chip with a picture beside one without
     reads as a picture that failed to load. */
  .info .swatch.photo { display: inline-flex; align-items: center; gap: 9px; padding: 5px 14px 5px 5px; }
  .info .swatch .sw-img {
    width: 34px;
    height: 34px;
    border-radius: var(--fichi-radius-full);
    object-fit: cover;
    display: block;
    background: var(--fichi-bg-muted);
  }
  .info .swatch.on {
    border-color: var(--store-accent);
    background: color-mix(in srgb, var(--store-accent) 12%, transparent);
    color: var(--fichi-text-primary);
    cursor: default;
  }
  /* The picked value, named in the heading so a reader who cannot see which
     chip is filled still knows: «Color: Negro», «Talla: M». */
  .info .pick-value { font-weight: 700; color: var(--fichi-text-primary); }
  /* Sizes are the same chips, squarer: a size is a short token and a pill
     around "M" reads as a button with nothing in it. */
  .info .sizes {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .info .size {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 46px;
    padding: 8px 12px;
    border: 1px solid var(--fichi-border-default);
    border-radius: var(--fichi-radius-md);
    font-size: 14px;
    font-weight: 600;
    color: var(--fichi-text-secondary);
    text-decoration: none;
    transition: border-color 140ms, color 140ms;
  }
  .info a.size:hover { border-color: var(--store-accent); color: var(--fichi-text-primary); }
  .info .size.on {
    border-color: var(--store-accent);
    background: color-mix(in srgb, var(--store-accent) 12%, transparent);
    color: var(--fichi-text-primary);
    cursor: default;
  }
  /* A size this colour is not made in. Struck, not hidden: a customer who
     wants a G in white should see that G exists and white does not come in
     it, rather than wonder whether the shop sells G at all. */
  .info .size.off {
    color: var(--fichi-text-muted);
    border-style: dashed;
    text-decoration: line-through;
    cursor: not-allowed;
  }
  .info .pick-note { margin: 8px 0 0; font-size: 13px; color: var(--fichi-text-muted); }
  .encargo-link { margin: 22px 0 0; font-size: 14.5px; color: var(--fichi-text-secondary); }
  .encargo-link a { color: var(--store-accent-text); font-weight: 600; }
  .stock { margin: 26px 0 0; }
  .stock ul { list-style: none; margin: 0; padding: 0; }
  .stock li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px;
    font-size: 14px;
    border: 1px solid var(--fichi-border-subtle);
    border-radius: var(--fichi-radius-md);
    background: var(--fichi-bg-surface);
  }
  .stock li + li { margin-top: 8px; }
  .datecheck { margin: 26px 0 0; }
  .datecheck .dc-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
  .datecheck .dc-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--fichi-text-secondary);
  }
  .datecheck .dc-field input {
    height: 42px;
    padding: 0 12px;
    border-radius: var(--fichi-radius-md);
    border: 1px solid var(--fichi-border-subtle);
    background: var(--fichi-bg-surface);
    color: var(--fichi-text-primary);
    font: inherit;
    font-size: 14px;
  }
  .datecheck .dc-go {
    height: 42px;
    padding: 0 20px;
    border-radius: var(--fichi-radius-full);
    border: 1px solid var(--store-accent);
    background: transparent;
    color: var(--store-accent-text);
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
  }
  .datecheck .dc-out { margin: 12px 0 0; font-size: 14.5px; color: var(--fichi-text-secondary); min-height: 1px; }
  .datecheck .dc-out.yes { color: var(--fichi-text-primary); font-weight: 600; }
  .datecheck .dc-out.no { color: var(--fichi-text-muted); }
  .stock .stock-note { margin: 10px 0 0; font-size: 13.5px; color: var(--fichi-text-muted); }
  .stock .branch { color: var(--fichi-text-primary); font-weight: 600; }
  .stock .count {
    color: var(--fichi-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* Out of stock reads quieter, not louder: the message is "not here today",
     and a red badge on a shop's own page punishes honesty. */
  .stock li.out .branch, .stock li.out .count { color: var(--fichi-text-muted); }
  /* The decision, right where it is made.
     This used to be a bar at the very BOTTOM of the page, below the related
     products — so a visitor read the price, then walked through four OTHER
     products, and only then found the button for the one they were looking at.
     It also printed the price a second time. One price, one button, both next
     to the availability they depend on. */
  .buy { display: flex; flex-direction: column; gap: 10px; margin: 24px 0 0; }
  /* "Agregar a mi lista" from the DETAIL page. Until now the only add button
     in the whole storefront lived on a catalog CARD, so a customer who opened
     a product — read the description, picked a colour, checked the sucursal —
     had to go BACK to the grid to put it in their list. The page that answers
     every question about a product could not act on the answer. */
  .buy .to-cart {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 14px 22px;
    border-radius: var(--fichi-radius-full);
    border: 1.5px solid var(--store-accent);
    background: transparent;
    color: var(--store-accent-text);
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
  }
  /* One button, two states, no client code beyond the aria-pressed the cart
     already paints on every [data-add] on the page. */
  .buy .to-cart .l-ok { display: none; }
  .buy .to-cart[aria-pressed="true"] {
    background: color-mix(in srgb, var(--store-accent) 12%, var(--fichi-bg-page));
    border-style: dashed;
  }
  .buy .to-cart[aria-pressed="true"] .l-add { display: none; }
  .buy .to-cart[aria-pressed="true"] .l-ok { display: flex; align-items: center; gap: 9px; }
  .buy .whatsapp {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 15px 22px;
    border-radius: var(--fichi-radius-full);
    background: var(--store-accent);
    color: var(--store-accent-contrast);
    font-size: 16px;
    font-weight: 600;
    text-decoration: none;
    box-shadow: var(--fichi-shadow-brand);
  }
  .buy .back-link {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 14px 22px;
    border-radius: var(--fichi-radius-full);
    border: 1px solid var(--fichi-border-default);
    font-size: 15px;
    font-weight: 600;
    color: var(--store-accent-text);
    text-decoration: none;
  }
  /* Related products: the catalog's own cards, so a product looks the same
     here as on the home. The catalog grid is four-up at 992px; the
     product column is 640px, so two-up reads right and never squeezes.
     Its own section AFTER the product, with a rule above it: these are a
     different subject, and the separator is what says so. */
  /* No max-width and no inset here: this section already sits INSIDE .shell,
     and re-applying the column narrowed it by a second --store-inset — the
     rule above it stopped lining up with the text it separates. */
  .related {
    margin-top: 44px;
    padding-top: 30px;
    border-top: 1px solid var(--fichi-border-subtle);
  }
  .related h2 {
    margin: 0 0 14px;
    font-family: var(--fichi-font-display);
    font-size: 17px;
    font-weight: 600;
    color: var(--fichi-text-primary);
  }
  .related .catalog { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .section-head {
    max-width: var(--store-content);
    margin: var(--store-gap) auto 0;
    width: calc(100% - var(--store-inset));
    display: flex;
    align-items: baseline;
    justify-content: space-between;
  }
  .section-head h2 {
    margin: 0;
    font-family: var(--fichi-font-display);
    font-size: 19px;
    font-weight: 600;
  }
  .section-head .count { font-size: 13px; color: var(--fichi-text-muted); }
  .catalog {
    max-width: var(--store-content);
    margin: var(--store-gap-inner) auto 0;
    width: calc(100% - var(--store-inset));
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
  }
  /* A phone at 390px minus the 32px inset leaves 358px, and this grid had no
     breakpoint of its own: minmax(200px, 1fr) resolved to ONE column of 358px
     cards, which for a 252-item rentals catalog is ~6,000px of scrolling even
     after filtering. Two columns halve it.

     It belongs HERE, in the CSS every catalog ships, not in the filter
     module's: a shop that turns "Mostrar buscador y filtros" off still has
     customers on phones. */
  @media (max-width: 640px) {
    .catalog { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  }
  .cell { position: relative; display: flex; }
  .cell > .card { flex: 1; min-width: 0; }
  /* The quick-add sits ON the photo, out of the link's way. 40px so a thumb
     hits it without hitting the card underneath. */
  .cell .add {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fichi-radius-full);
    border: 1px solid var(--fichi-border-subtle);
    background: var(--fichi-bg-surface);
    color: var(--fichi-text-primary);
    box-shadow: var(--fichi-shadow-sm);
    cursor: pointer;
    padding: 0;
  }
  .cell .add .i-ok { display: none; }
  .cell .add[aria-pressed="true"] {
    background: var(--store-accent);
    border-color: var(--store-accent);
    color: var(--store-accent-contrast);
  }
  .cell .add[aria-pressed="true"] .i-add { display: none; }
  .cell .add[aria-pressed="true"] .i-ok { display: block; }
  .card {
    display: flex;
    flex-direction: column;
    border-radius: var(--fichi-radius-lg);
    background: var(--fichi-bg-surface);
    border: 1px solid var(--fichi-border-subtle);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    box-shadow: var(--fichi-shadow-sm);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
  }
  .card:hover { transform: translateY(-3px); box-shadow: var(--fichi-shadow-md); }
  .card .media { background: var(--fichi-bg-muted); }
  .card img, .card .placeholder {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    display: block;
  }
  .card .placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 44px;
    font-weight: 700;
    font-family: var(--fichi-font-display);
    color: var(--fichi-text-muted);
  }
  .card-body { display: flex; flex-direction: column; gap: 6px; padding: 14px 14px 16px; }
  /* "En 3 colores" — a fact about the model, sized under the price it follows.
     When every colour has a photo the row shows those photos: the label a shop
     types is a word ("Carey", "Palo de rosa") and only the shop knows what it
     looks like, but the photo of that colour's own product does. */
  .card .variants { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--fichi-text-muted); }
  .card .variants img {
    width: 16px;
    height: 16px;
    border-radius: var(--fichi-radius-full);
    object-fit: cover;
    display: block;
    background: var(--fichi-bg-muted);
  }
  .card .name {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--fichi-text-primary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .card .price {
    font-size: 15px;
    font-weight: 700;
    color: var(--store-accent-text);
    font-variant-numeric: tabular-nums;
  }
  .price, .rail-price { display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
  .was {
    font-size: 13px;
    font-weight: 500;
    color: var(--fichi-text-muted);
    text-decoration: line-through;
  }
  .now { text-decoration: none; }
  .off {
    align-self: center;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--store-accent);
    color: var(--store-accent-contrast);
    font-size: 11px;
    font-weight: 700;
    line-height: 1.6;
    white-space: nowrap;
  }
#g-0:checked~.main-wrap .m-0{display:block}#g-0:checked~.thumbs .t-0{border-color:var(--store-accent)}#g-0:focus-visible~.thumbs .t-0{outline:2px solid var(--store-accent);outline-offset:2px}#g-1:checked~.main-wrap .m-1{display:block}#g-1:checked~.thumbs .t-1{border-color:var(--store-accent)}#g-1:focus-visible~.thumbs .t-1{outline:2px solid var(--store-accent);outline-offset:2px}
  .gallery .main-wrap { position: relative; }
  .gallery .main.leaving {
    display: block;
    position: absolute;
    inset: 0;
    margin: auto;
    width: calc(100% - 48px);
    pointer-events: none;
  }
  .thumbs { position: relative; }
  .thumbs .ring {
    position: absolute;
    left: 0;
    top: 0;
    width: 64px;
    height: 64px;
    border: 2px solid var(--store-accent);
    border-radius: var(--fichi-radius-md);
    pointer-events: none;
  }
  .thumbs.gliding .thumb { border-color: var(--fichi-border-subtle) !important; transition: none; }
  @media (prefers-reduced-motion: reduce) {
    .gallery .main.leaving, .thumbs .ring { display: none !important; }
    .thumbs .thumb { transition: none; }
  }

  .card .media { position: relative; }
  .rail .rail-card .rail-photo { display: block; position: relative; }
  /* Selectors one step heavier than the images' own rules: the rail sizes its
     pictures with .rail .rail-card img (0,2,1), and a lighter hide lost to it —
     the second photo rendered as a block under the cover, doubling the card. */
  .card .media .alt, .rail .rail-card .alt { display: none; }
  @media (hover: hover) and (pointer: fine) {
    .card .media .alt, .rail .rail-card .alt {
      display: block;
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      opacity: 0;
      transition: opacity 0.2s ease;
    }
    .card:hover .media .alt, .card:focus-visible .media .alt,
    .rail .rail-card:hover .alt, .rail .rail-card:focus-visible .alt { opacity: 1; }
  }
  .navbar {
    position: sticky;
    top: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 12px 24px;
    background: var(--fichi-bg-surface);
    border-bottom: 1px solid var(--fichi-border-subtle);
    /* The bar's accent surface: without this the section's accent override
       had almost nothing to colour (search and cart are neutral chrome), so
       changing "Color" looked like it did nothing. */
    box-shadow: inset 0 -3px 0 0 var(--store-accent);
  }
  .navbar .brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-family: var(--fichi-font-display);
    font-size: 17px;
    font-weight: 700;
    color: var(--fichi-text-primary);
    text-decoration: none;
    flex-shrink: 0;
  }
  .navbar .brand img { height: 30px; max-width: 150px; object-fit: contain; display: block; }
  /* Text brand (no logo) carries the accent — the most visible surface a
     store without a logo has. */
  .navbar .brand.text-brand { color: var(--store-accent-text); }
  .navbar .links { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
  .navbar .links a {
    font-size: 14px;
    font-weight: 500;
    color: var(--fichi-text-secondary);
    text-decoration: none;
  }
  .navbar .links a:hover { color: var(--store-accent-text); }
  .navbar .search {
    flex: 1;
    min-width: 120px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border-radius: var(--fichi-radius-full);
    border: 1px solid var(--fichi-border-subtle);
    background: var(--fichi-bg-page);
    color: var(--fichi-text-muted);
  }
  /* 16px, not 13px: beside a 17px brand the field read as an afterthought, and
     iOS Safari zooms the whole page when a field under 16px takes focus. */
  .navbar .search input {
    flex: 1;
    border: 0;
    outline: 0;
    background: transparent;
    font-size: 16px;
    color: var(--fichi-text-primary);
    font-family: inherit;
    min-width: 0;
  }
  /* The visitor's theme toggle is FIXED at top:14/right:14 and 40px wide, and
     it paints above this bar (z 50 over 40). Measured on the live storefront,
     it covered the cart icon completely — 20px of icon inside 40px of button,
     at every desktop width. Reserving its corner is the only fix that holds:
     the toggle cannot know whether a navbar exists below it. */
  .navbar { padding-right: 64px; }
  .navbar .cart {
    color: var(--store-accent);
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
  }
  .navbar button.cart { cursor: pointer; min-height: 44px; }
  .navbar .cart .cart-count {
    min-width: 18px;
    padding: 1px 5px;
    border-radius: var(--fichi-radius-full);
    background: var(--store-accent);
    color: var(--store-accent-contrast);
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1.4;
    text-align: center;
  }
  /* A phone: three rows, in the order a thumb expects them.
     Row 1 — the brand at the left and the cart at the right, just inside the
     corner reserved for the theme toggle. Row 2 — the links, on a line of
     their own. Row 3 — the search, full width. Before this the children
     wrapped in DOM order: brand and links filled the first row, the cart fell
     to a second row by itself at the left, and the search came third —
     which read as a header that had broken rather than one that adapted. */
  /* The burger, hidden until a phone asks for it. Sized to the 44px tap target
     the audit holds every control to. */
  .navbar .nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--fichi-border-subtle);
    border-radius: 10px;
    background: transparent;
    color: var(--fichi-text-primary);
    cursor: pointer;
  }
  .navbar .nav-toggle:hover { background: var(--fichi-bg-elevated); }

  @media (max-width: 720px) {
    .navbar { flex-wrap: wrap; padding: 10px 64px 10px 16px; gap: 10px 12px; }
    .navbar .brand { order: 0; flex: 1 1 auto; min-width: 0; }
    .navbar .brand.text-brand { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .navbar .cart { order: 1; margin-left: auto; }
    .navbar .links { order: 2; flex-basis: 100%; gap: 6px 16px; }
    .navbar .search { order: 3; flex-basis: 100%; }

    /* «Botón de menú»: the links collapse behind the toggle and drop as a
       panel when it is pressed. Everything else on the bar keeps its place,
       so the brand, the cart and the search do not move when the menu opens.

       Toggled with a CLASS on the nav rather than the [hidden] attribute:
       [hidden] comes from the UA stylesheet and loses to any rule that sets
       display, which is exactly what the .links rule above does. */
    .navbar-burger .nav-toggle { display: inline-flex; order: 1; }
    .navbar-burger .cart { order: 2; margin-left: 0; }
    .navbar-burger .links { display: none; }
    .navbar-burger.nav-open .links,
    .navbar-burger.nav-closing .links {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      padding-top: 4px;
      border-top: 1px solid var(--fichi-border-subtle);
    }
    .navbar-burger.nav-open .links a,
    .navbar-burger.nav-closing .links a {
      padding: 12px 4px;
      border-bottom: 1px solid var(--fichi-border-subtle);
    }
    .navbar-burger.nav-open .links a:last-child,
    .navbar-burger.nav-closing .links a:last-child { border-bottom: 0; }

    /* «Desde un lado»: a drawer over the page instead of a panel that pushes
       it. The page keeps its scroll position, so a visitor who opens the menu
       by accident does not lose their place, and the links get the whole
       screen rather than shoving the article off the bottom.

       It is NOT a display change like the drop panel, so it needs none of that
       one's machinery: the drawer is always in the layout and travels on a
       transform, which transitions in BOTH directions by itself. visibility is
       what keeps it out of the tab order and away from a screen reader while
       it is shut, delayed on the way out so it outlives its own exit. */
    /* Where the drawer's own content starts: clear of the bar's row, so the
       first link never sits under the X. Declared here and overwritten by the
       script when the drawer opens, the way --store-navbar-height already
       works — a var() that only ever exists in JS drops its whole declaration
       for the frame before the script runs, and the guard in
       token-exists.test.ts refuses one. 68px is the X's row on a bare bar. */
    .navbar-burger.nav-side { --store-drawer-top: 68px; }
    .navbar-burger.nav-side .links,
    .navbar-burger.nav-side.nav-closing .links {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      position: fixed;
      /* The WHOLE height of the screen: the owner asked for the menu and
         nothing else — no search field, no cart, no announcement strip showing
         past its edge. Only the X stays on top of it, because the control that
         opened the drawer has to be the one that closes it.

         The content starts below the bar's row, and that number is MEASURED
         when the drawer opens: a fixed box cannot know where a STICKY bar
         currently sits, since above the fold an announcement band is still
         pushing it down. */
      inset: 0 auto 0 0;
      width: min(86vw, 340px);
      z-index: 70;
      padding: var(--store-drawer-top) 20px 24px;
      overflow-y: auto;
      overscroll-behavior: contain;
      background: var(--fichi-bg-surface);
      border-top: 0;
      border-right: 1px solid var(--fichi-border-subtle);
      box-shadow: var(--fichi-shadow-lg);
      transform: translateX(-101%);
      visibility: hidden;
      transition: transform 260ms cubic-bezier(0.2, 0, 0, 1), visibility 0s linear 260ms;
    }
    .navbar-burger.nav-side.nav-open .links {
      transform: none;
      visibility: visible;
      transition: transform 260ms cubic-bezier(0.2, 0, 0, 1), visibility 0s;
    }
    /* The scrim is a real button: tapping beside a drawer to shut it is what
       everyone expects, and a div would hand that gesture to a mouse alone. */
    .navbar-burger .nav-scrim {
      position: fixed;
      inset: 0;
      z-index: 69;
      padding: 0;
      border: 0;
      background: rgba(0, 0, 0, 0.4);
      opacity: 0;
      visibility: hidden;
      transition: opacity 260ms ease, visibility 0s linear 260ms;
    }
    .navbar-burger.nav-side.nav-open .nav-scrim {
      opacity: 1;
      visibility: visible;
      transition: opacity 260ms ease, visibility 0s;
    }
    /* The toggle ALONE rides above the drawer. The burger is the X: the
       control that opened the menu closes it, in the corner the thumb left it.
       Everything else on the bar stays under the drawer, which is the point of
       a full-height panel. */
    .navbar-burger.nav-side .nav-toggle { position: relative; z-index: 71; }
    /* An open drawer has to clear the page's own stacked things: the cart bar
       sits at 62 and the catalogue's filter sheet at 70. */
    .navbar-burger.nav-side.nav-open { z-index: 80; }

  }

  /* The panel is a display change, so it cannot be TRANSITIONED — an animation
     is what runs when an element appears, and it needs no @starting-style, so
     it works on every phone that will ever open this. The close is the mirror,
     driven from the script: .nav-closing holds the panel in the layout for
     exactly as long as the animation lasts.

     The whole block is behind no-preference rather than reset inside a
     reduce query, because the stagger below is keyed on :nth-child and would
     OUT-SPECIFY any reset: the delays would survive it, and with a both fill a
     link sits at opacity 0 for the length of its delay. Someone who asked for
     less movement would get a menu whose links arrive blank — the one thing
     reduced motion must never produce. Declaring the movement only for whoever
     wants it cannot fail that way. */
  @media (max-width: 720px) and (prefers-reduced-motion: no-preference) {
    /* :not(.nav-side) throughout — the drawer moves on a transform that
       transitions both ways by itself, and laying a keyframed slide over a
       transition on the same property makes one of them win at random. */
    .navbar-burger:not(.nav-side).nav-open .links { animation: nav-in 240ms cubic-bezier(0.2, 0, 0, 1) both; }
    .navbar-burger:not(.nav-side).nav-closing .links { animation: nav-out 160ms cubic-bezier(0.4, 0, 1, 1) both; }
    /* The links arrive just behind the panel, close enough together to read as
       one movement. Capped at six: past that the last link waits on a queue.
       The drawer gets them too: there the panel travels and the links fade in
       behind it, which is the same idea on a different axis. */
    .navbar-burger.nav-open .links > * { animation: nav-item-in 220ms cubic-bezier(0.2, 0, 0, 1) both; }
    .navbar-burger.nav-open .links > :nth-child(2) { animation-delay: 30ms; }
    .navbar-burger.nav-open .links > :nth-child(3) { animation-delay: 60ms; }
    .navbar-burger.nav-open .links > :nth-child(4) { animation-delay: 90ms; }
    .navbar-burger.nav-open .links > :nth-child(5) { animation-delay: 120ms; }
    .navbar-burger.nav-open .links > :nth-child(n + 6) { animation-delay: 150ms; }
  }

  @keyframes nav-in { from { opacity: 0; transform: translateY(-8px); } }
  @keyframes nav-out { to { opacity: 0; transform: translateY(-8px); } }
  @keyframes nav-item-in { from { opacity: 0; transform: translateY(-6px); } }

  /* The burger becomes the X that closes it: the top and bottom rules meet in
     the middle of the 24-unit box (y=7 and y=17 both travel 5 to y=12) and
     cross there, and the middle one leaves. Translate THEN rotate — the other
     order swings the line off the centre before it turns. The X itself is not
     movement for its own sake, so it stays under reduce; only its travel
     goes, which leaves the icon telling the truth about the menu's state. */
  .navbar .nav-toggle svg path {
    transform-box: view-box;
    transform-origin: 12px 12px;
    transition: transform 240ms cubic-bezier(0.2, 0, 0, 1), opacity 140ms ease;
  }
  .navbar.nav-open .nav-toggle svg path:nth-child(1) { transform: rotate(45deg) translateY(5px); }
  .navbar.nav-open .nav-toggle svg path:nth-child(2) { opacity: 0; }
  .navbar.nav-open .nav-toggle svg path:nth-child(3) { transform: rotate(-45deg) translateY(-5px); }

  @media (prefers-reduced-motion: reduce) {
    .navbar .nav-toggle svg path { transition-duration: 0.01ms; }
  }

  /* The catalogue's filter panel sticks at 16px, which is under this bar:
     measured at 1280px, the bar held 0-69px and covered the panel's first
     53px, its search field whole. Below a bar that sticks, the panel sticks
     16px below the bar's bottom edge. The bar's script writes its real height
     on the panel, so links that wrap to a second row (92px with eight at
     1280px, 127px at 861px) no longer cover it. Without the script it is the
     bar on one row: 12px of padding, the cart's 44px, 12px and the 1px rule.
     ".navbar ~ *" is a catalogue after the bar, in the box the bar sticks in:
     main on the home, body on a page that borrows it. A styled bar sticks in
     its .sec wrapper instead, with rules of its own. Only while the panel is
     a sidebar; at 860px and under it is a bottom sheet with top: auto.
     «Encabezado fijo» off puts the 16px back (appearance.ts). */
  @media (min-width: 861px) {
    .navbar ~ * .facets { --store-navbar-height: 69px; top: calc(var(--store-navbar-height) + 16px); }
  }

  .navbar .nav-item { position: relative; display: inline-flex; align-items: center; gap: 2px; }
  .navbar .sub-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 32px;
    min-height: 32px;
    padding: 0 4px;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--fichi-text-secondary);
    font: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
  }
  .navbar .sub-toggle:hover { color: var(--store-accent-text); }
  /* «Categorías» is text, and text in this bar starts flush with its gap —
     a plain link has no padding, so 4px here showed as a stagger on a phone,
     where the row below starts at the same edge. */
  .navbar .sub-label { padding-left: 0; }
  .navbar .sub-toggle .chev { display: inline-flex; transition: transform 0.15s; }
  .navbar .nav-item.sub-open > .sub-toggle .chev { transform: rotate(180deg); }
  .navbar .submenu {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    z-index: 45;
    min-width: 220px;
    max-width: min(320px, calc(100vw - 32px));
    margin: 0;
    padding: 8px;
    list-style: none;
    background: var(--fichi-bg-surface);
    border: 1px solid var(--fichi-border-subtle);
    border-radius: 12px;
    box-shadow: var(--fichi-shadow-lg);
  }
  .navbar .nav-item.sub-open > .submenu { display: block; }
  .navbar .submenu a {
    display: block;
    padding: 8px 10px;
    border-radius: 8px;
    color: var(--fichi-text-primary);
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
  }
  .navbar .submenu a:hover { background: var(--fichi-bg-page); color: var(--store-accent-text); }
  .navbar .submenu ul { margin: 0 0 4px; padding: 0 0 0 12px; list-style: none; }
  .navbar .submenu ul a { padding: 6px 10px; font-weight: 400; color: var(--fichi-text-secondary); }

  @media (max-width: 720px) {
    .navbar .nav-item { flex-wrap: wrap; }
    /* «Take the whole row» — and that is only what flex-basis: 100% MEANS
       while .links is a row. In the drawer .links is a COLUMN, where the main
       axis is the height: the same declaration made an open submenu 717px
       tall, swallowing the panel and stacking the other links on top of it.
       There the item already spans the width, from align-items: stretch, so
       the rule is scoped away rather than undone afterwards. */
    .navbar:not(.nav-side) .nav-item.sub-open { flex-basis: 100%; }
    .navbar .sub-toggle { min-width: 44px; min-height: 44px; }
    .navbar .submenu { position: static; flex-basis: 100%; min-width: 0; max-width: none; margin-top: 4px; box-shadow: none; }
    .navbar-burger.nav-open .links .nav-item,
    .navbar-burger.nav-closing .links .nav-item { border-bottom: 1px solid var(--fichi-border-subtle); }
    .navbar-burger.nav-open .links .nav-item > a,
    .navbar-burger.nav-closing .links .nav-item > a { flex: 1; border-bottom: 0; }
    .navbar-burger.nav-open .sub-label { flex: 1; justify-content: space-between; padding: 0 4px; }
    .navbar-burger.nav-open .submenu { border: 0; padding: 0 0 8px 12px; }
    .navbar-burger.nav-open .submenu a { padding: 8px 10px; border-bottom: 0; }
  }

  .navbar .search { position: relative; }
  /* The field sets outline: 0 for its own box, which also took the store's one
     focus ring off it (.navbar .search input outranks input:focus-visible). The
     pill carries the ring instead — a combobox nobody can see focused is one a
     keyboard user cannot find. */
  .navbar .search:focus-within { outline: 2px solid var(--store-ring, var(--store-accent)); outline-offset: 2px; }
  .navbar .search input::placeholder { color: var(--fichi-text-muted); opacity: 1; }
  .navbar .suggest {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    z-index: 45;
    max-height: min(70vh, 460px);
    overflow-y: auto;
    padding: 6px;
    background: var(--fichi-bg-surface);
    border: 1px solid var(--fichi-border-subtle);
    border-radius: 14px;
    box-shadow: var(--fichi-shadow-lg);
    color: var(--fichi-text-primary);
  }
  /* [hidden] comes from the UA stylesheet and loses to any rule that sets
     display; this one says it outright. */
  .navbar .suggest[hidden] { display: none; }
  .navbar .suggest-group + .suggest-group,
  .navbar .suggest-group + .suggest-all { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--fichi-border-subtle); }
  .navbar .suggest-label {
    padding: 8px 10px 4px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--fichi-text-muted);
  }
  .navbar .suggest [role="option"] {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    padding: 6px 10px;
    border-radius: 10px;
    cursor: pointer;
  }
  .navbar .suggest [role="option"]:hover,
  .navbar .suggest [role="option"][aria-selected="true"] { background: var(--fichi-bg-page); }
  /* The active option is marked by a shape as well as a tint: on the dark base
     the tint alone is a step of a few percent. */
  .navbar .suggest [role="option"][aria-selected="true"] { box-shadow: inset 3px 0 0 var(--store-accent); }
  .navbar .suggest .thumb {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    object-fit: cover;
    background: var(--fichi-bg-muted);
    font-family: var(--fichi-font-display);
    font-weight: 700;
    color: var(--fichi-text-muted);
  }
  .navbar .suggest .txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
  .navbar .suggest .name,
  .navbar .suggest .meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .navbar .suggest .name { font-size: 14px; font-weight: 600; line-height: 1.3; }
  .navbar .suggest .meta { font-size: 12.5px; color: var(--fichi-text-secondary); }
  .navbar .suggest .price {
    flex-shrink: 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--store-accent-text);
    font-variant-numeric: tabular-nums;
  }
  .navbar .suggest .suggest-all { font-size: 14px; font-weight: 600; color: var(--store-accent-text); }
  /* The live region that says how many suggestions there are: read, not seen. */
  .navbar .suggest-status {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
  /* A styled band clips what overflows it (that is how its rounded corners
     hold), and the list hangs below the bar. The band lets it out only while
     it is open. */
  .sec-band:has(.navbar .search [aria-expanded="true"]) { overflow: visible; }
  @media (max-width: 720px) {
    .navbar .suggest { max-height: 60vh; }
  }
  .shop-footer {
    margin-top: 40px;
    padding: 32px 24px 12px;
    background: color-mix(in srgb, var(--store-accent) 16%, var(--fichi-bg-page));
  }
  .shop-footer .inner {
    max-width: var(--store-content);
    margin: 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 28px 40px;
    justify-content: space-between;
  }
  /* The shop's own block takes the room the link columns leave: one column of
     links used to sit alone at the left of a band that was otherwise empty. */
  .shop-footer .shop { flex: 1 1 240px; max-width: 360px; }
  .shop-footer .shop-name {
    margin: 0 0 8px;
    font-family: var(--fichi-font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--fichi-text-primary);
  }
  .shop-footer .shop-line {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin: 0 0 6px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--fichi-text-secondary);
  }
  .shop-footer .shop-line svg { flex-shrink: 0; margin-top: 2px; }
  .shop-footer a.shop-line { color: var(--store-accent-text); font-weight: 500; }
  /* The layout's «Tienda creada con Rachi» line comes right after <main> on
     every page. Left alone under this tinted band it sat on the page
     background and read as a second, unrelated footer. Only when this footer
     is the LAST thing in <main> and not boxed by a section style does it make
     sense to pull the line in — a boxed footer is a card, and a tinted strip
     under a card would be the same mistake the other way round. */
  main:has(> .shop-footer:last-child) ~ .fichi-footer {
    margin-top: 0;
    flex-grow: 1;
    padding: 14px 24px 22px;
    background: color-mix(in srgb, var(--store-accent) 16%, var(--fichi-bg-page));
    border-top: 1px solid color-mix(in srgb, var(--store-accent) 28%, transparent);
    /* The layout paints this line in the muted ink, which is fine on the page
       background and measures 3.94:1 on the tint (axe, light theme). The
       band's own links are the secondary ink on the same tint and pass. */
    color: var(--fichi-text-secondary);
  }
  main:has(> .shop-footer:last-child) ~ .fichi-footer strong { color: var(--fichi-text-primary); }
  main:has(> .shop-footer:last-child) > .shop-footer { padding-bottom: 24px; }
  .shop-footer h3 {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 700;
    color: var(--fichi-text-primary);
  }
  .shop-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
  .shop-footer a { font-size: 13px; color: var(--fichi-text-secondary); text-decoration: none; }
  .shop-footer a:hover { color: var(--store-accent-strong); }
  .shop-footer .social { display: flex; gap: 10px; }
  .shop-footer .social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--fichi-radius-full);
    background: var(--fichi-bg-surface);
    color: var(--store-accent-text);
    box-shadow: var(--fichi-shadow-sm);
  }

  body > .shop-footer ~ .fichi-footer {
    margin-top: 0;
    flex-grow: 1;
    padding: 14px 24px 22px;
    background: color-mix(in srgb, var(--store-accent) 16%, var(--fichi-bg-page));
    border-top: 1px solid color-mix(in srgb, var(--store-accent) 28%, transparent);
    color: var(--fichi-text-secondary);
  }
  body > .shop-footer ~ .fichi-footer strong { color: var(--fichi-text-primary); }
  body > .shop-footer { padding-bottom: 24px; }
