:root {

    --base-font-size: 16px;
    font-size: var(--base-font-size);
 
    --heading-font-size-factor: 1.2;
    --h1-font-size: calc(var(--base-font-size) * 2.5 * var(--heading-font-size-factor));
    --h2-font-size: calc(var(--base-font-size) * 2 * var(--heading-font-size-factor));
    --h3-font-size: calc(var(--base-font-size) * 1.8 * var(--heading-font-size-factor));
    --h4-font-size: calc(var(--base-font-size) * 1.4 * var(--heading-font-size-factor));
    --h5-font-size: calc(var(--base-font-size) * 1.2 * var(--heading-font-size-factor));
    --h6-font-size: calc(var(--base-font-size) * 1 * var(--heading-font-size-factor));;

    --color-primary: #222222;
    --color-accent: #b2674d;
    --color-discounted-price: #5c4033;

    --color-success: 90, 151, 124;
    --color-alert: 153, 64, 75;

    --color-text: #4a4a4a;
    --color-navbar: #2b2b2b;
    --color-footer: #f5f3f0;
    --color-foreground: #4a4a4a;
    --color-background: #ffffff;

    --bg-body: #ffffff;
    --bg-header: #e3ded7;
    --bg-card: #ffffff;
    --bg-footer: #2b2b2b;
    --bg-overlay: 146, 146, 146;

    --gap: 2rem;
    --hover-opacity: 0.5;

    --button-py: 1rem;
    --button-px: 2rem;
    --button-rounding: 0.125rem;
    --button-text: var(--color-text);
    --button-text-primary: #ffffff;
    --button-border: 1px solid transparent;

    --input-bg: #f5f3f0;
    --input-border-color: #f5f3f0;
    --input-border: 1px solid var(--input-border-color);
    --input-color: #2b2b2b;
    --input-rounding: 0.5rem;
    --input-px: 1rem;
    --input-py: 0.75rem;

    --box-shadow: '';

    --bg-campaignbar: #e3ded7;
    --color-campaignbar: #4a4a4a;


    /* Swiper */
    --swiper-navigation-color: var(--color-text);
    --swiper-pagination-color: var(--color-accent);
    --swiper-navigation-size: 2rem;
    --swiper-theme-color: var(--color-primary);
}















body {
    font-family: 'Montserrat',sans-serif !important;
    overflow: overlay;
}

.font-body {
    font-family: 'Montserrat',sans-serif;
}

h1, h2, h3, h4, h5, h6, .font-heading {
    font-family: 'Bodoni Moda',serif-serif;
    font-weight: bold;
    line-height: 120%;
}

.text-h1 {
    font-size: var(--h1-font-size);
}

.text-h2 {
    font-size: var(--h2-font-size);
}

.text-h3 {
    font-size: var(--h3-font-size);
}

.text-h4 {
    font-size: var(--h4-font-size);
}

.text-h5 {
    font-size: var(--h5-font-size);
}

.text-h6 {
    font-size: var(--h6-font-size);
}

.gap-size {
    gap: var(--gap);
}

.gap-size-2 {
    gap: calc(var(--gap) * 2);
}

.hover-opacity:hover {
    opacity: var(--hover-opacity);
}

/**
 * Cards
 */

.bg-card {
    background-color: var(--bg-card);
}

/**
 * Primary color
 */ 
.text-primary {
    color: var(--color-primary);
}
.hover\:text-primary:hover {
    color: var(--color-primary);
}
.ring-primary,
.ring-primary:focus {
    --tw-ring-color: var(--color-primary);
}
.bg-primary,
.bg-primary[type="button"], .bg-primary[type="submit"], .bg-primary[type="reset"], button.bg-primary {
    background-color: var(--color-primary);
}
.hover\:bg-primary:hover {
    background-color: var(--color-primary);
}
.border-primary {
    border-color: var(--color-primary);
}

/**
 * Secondary color
 */ 
.text-secondary {
    color: var(--color-accent);
}
.hover\:text-secondary:hover {
    color: var(--color-accent);
}
.ring-secondary {
    --tw-ring-color: var(--color-accent);
}
.bg-secondary {
    background-color: var(--color-accent);
}
.hover\:bg-secondary:hover {
    background-color: var(--color-accent);
}
.border-secondary,
.focus\:border-secondary:focus {
    border-color: var(--color-accent);
}

/**
 * Accent color
 */ 
.text-accent {
    color: var(--color-accent);
}
.hover\:text-accent:hover {
    color: var(--color-accent);
}
.ring-accent {
    --tw-ring-color: var(--color-accent);
}
.bg-accent {
    background-color: var(--color-accent) !important;
}
.hover\:bg-accent:hover {
    background-color: var(--color-accent);
}

/**
 * Discounted price color
 */ 
.text-discounted-price {
    color: var(--color-discounted-price, var(--color-accent));
}

/**
 * Navbar
 */ 
.text-navbar {
    color: var(--color-navbar);
}



/**
 * Foreground color
 */ 
.text-body {
    color: var(--color-text);
}
.hover\:text-body:hover {
    color: var(--color-text);
}
.divide-foreground>:not([hidden])~:not([hidden]),
.border-foreground {
    border-color: var(--color-foreground);
}
.hover\:border-foreground:hover {
    border-color: var(--color-foreground);
}
.border-foreground\/50 {
    border-color: var(--color-foreground)50;
}

.bg-foreground {
    background-color: var(--color-foreground);
}
.hover\:bg-foreground:hover {
    background-color: var(--color-foreground);
}

/**
 * Various background colors
 */

.bg-success {
    background: rgba(var(--color-success), 0.4);
}

.bg-alert {
    background-color: rgba(var(--color-alert), 0.4);
}

.bg-body {
    background-color: var(--bg-body);
}

.to-body {
    --tw-gradient-to: var(--bg-body) var(--tw-gradient-to-position) !important;
}

/**
 * Header
 */

.bg-header {
    background-color: var(--bg-header, transparent);
}
.border-header {
    border-color: var(--bg-header, transparent);
}

/**
 * Campaignbar
 */

.bg-campaignbar {
    background-color: var(--bg-campaignbar);
}
.text-campaignbar {
    color: var(--color-campaignbar);
}

/**
 * Footer
 */

.bg-footer {
    background-color: var(--bg-footer);
}

.text-footer {
    color: var(--color-footer);
}

/**
 * Overlay
 */

.bg-overlay {
    background-color: rgba(var(--bg-overlay), var(--tw-bg-opacity));
}

.border-highlight {
    border-color: var(--color-accent) !important;
}

/**
 * Buttons
 */

.button-py {
    padding-top: var(--button-py);
    padding-bottom: var(--button-py);
}
.button-px {
    padding-left: var(--button-px);
    padding-right: var(--button-px);
}
.button-rounding {
    border-radius: var(--button-rounding);
}
.button-text-primary {
    color: var(--button-text-primary);
}


/**
 * Form fields
 */

.input-bg {
    background-color: var(--input-bg);
}
.input-text {
    color: var(--input-color);
}
.input-border {
    border: var(--input-border);
}
.input-rounding {
    border-radius: 0.125rem;
}
.input-py {
    padding-top: var(--input-py);
    padding-bottom: var(--input-py);
}
.input-px {
    padding-left: var(--input-px);
    padding-right: var(--input-px);
}

/**
 * Cart bubble tweaks
 */
.cart-bubble.text-xs {
    font-size: 0.6rem;
    line-height: 1;
}

/**
 * Box shadows
 */






.shadow-default {
    box-shadow: 0 0 #0000;
}

/**
 * Transition duration
 */
.duration-default {
    transition-duration: 0.5s !important;
}


/**
 * Disable spinner arrows on number inputs
 */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
}

/**
 * Tailwind
 */
[multiple]:focus, [type=date]:focus, [type=datetime-local]:focus, [type=email]:focus, [type=month]:focus, [type=number]:focus, [type=password]:focus, [type=search]:focus, [type=tel]:focus, [type=text]:focus, [type=time]:focus, [type=url]:focus, [type=week]:focus, select:focus, textarea:focus {
    --tw-ring-color: var(--color-primary);
    outline: none;
    border-color: var(--color-primary);
}

/**
 * PhotoSwipe
 */
.pswp {
    --pswp-icon-color-secondary: var(--color-text);
    --pswp-icon-color: var(--color-text);
    --pswp-bg: var(--bg-body);
    --pswp-icon-stroke-color: var(--pswp-bg);
}

.pswp img {
    max-width: none;
    object-fit: contain;
}

.pswp__img--placeholder {
    display: none !important;
}

.pswp__counter {
    font-weight: bold;
    text-shadow: 0 0 2px var(--pswp-bg)
}

/**
 * Swiper
 */

 /** Fix for pinch zoom on main product image */
 .swiper.swiper-horizontal {
     touch-action: auto;
 }
 
.swiper-button-next,
.swiper-button-prev {
    width: auto;
}

.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
    display: none
}

.swiper-button-next:after,
.swiper-button-prev:after {
    content: '';
}

.products-swiper-main {
    min-height: 200px;
}

@media (max-width: 767px) {
    .images-wrapper {
        max-height: 50vh;
    }
}

.products-swiper-thumbs {
    --swiper-navigation-size: 30px;
}

.swiper-slide-thumb-active {
    opacity: 100;
}

@media (max-width: 767px) {
    .products-swiper-main .swiper-slide img {
        max-height: 50vh;
    }
}
@media (min-width: 768px) and (max-width: 1279px) {
    .products-swiper-main .swiper-slide img {
        max-height: 700px;
    }
}
@media (min-width: 1280px) {
    .products-swiper-main .swiper-slide img {
        max-height: 800px;
    }
}

/**
 * Tailwind 
 */

.aspect-1\/1 {
    aspect-ratio: 1 / 1;
}

.aspect-4\/3 {
    aspect-ratio: 4 / 3;
}

.aspect-3\/2 {
    aspect-ratio: 3 / 2;
}

.aspect-2\/1 {
    aspect-ratio: 2 / 1;
}

.aspect-5\/3 {
    aspect-ratio: 5 / 3;
}

.aspect-3\/4 {
    aspect-ratio: 3 / 4;
}

.cursor-zoom-in {
    cursor: zoom-in;
}

.scale-75 {
    transform: scaleX(0.75) scaleY(0.75);
}

.break-words {
    overflow-wrap: anywhere !important;
}

@media (min-width: 768px) {
    .md\:scale-100 {
        transform: scaleX(1) scaleY(1);
    }
}

@media (min-width: 1280px) {
    .container {
        max-width: 1280px;
    }
}

@media (min-width: 1480px) {
    .container {
        max-width: 1480px;
    }
}

select:not([size]) {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");
    background-position: right 0.5rem center;
    background-repeat: no-repeat;
    background-size: 1.5em 1.5em;
    padding-right: 2.5rem;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

.focus\:outline-none:focus {
    --tw-ring-color: transparent;
}

.hidden-empty:empty {
    display: none;
}

/**
 * Fix for modal max-height in desktop
 */
@media (min-width: 640px) {
    div[modal='search'] {
        max-height: 80vh;
    }
}

/**
 * Browser scrollbar (Webkit)
 */
body::-webkit-scrollbar {
    width: 4px;
    height: 4px;
    background-color: transparent;
}
body::-webkit-scrollbar-thumb {
    width: 4px;
    height: 4px;
    background-color: var(--color-primary);
    border-radius: 0.5rem;
}

/**
 * Wishlist
 */
.wishlist-alert {
    background: rgba(var(--color-success), 0.4);
    font-size: 1rem !important;
    padding: 1rem;
    margin-bottom: 1rem;
}

.wishlist-alert i {
    display: none;
}

.wishlist-alert .wishlist-addok {
    background: #f00;
}

.product [data-qb-selector="product-item"] > a {
    height: inherit !important;
    width: inherit !important;
}

.wishlist-form-save {
    margin-top: 2rem;
}

.wishlist-form-save .btn-primary {
}

.wishlist-sharebox {
    max-width: 100% !important;
    background: rgba(0,0,0,0.1) !important;
    border: none !important;
}

.wishlist-sharebox hr {
    margin: 1rem 0 1.5rem 0;
}

.wishlist-sharebox label {
    display: block;
    margin: 1rem 0 0.2rem 0;
}

.wishlist-sharebox input {
    margin-bottom: 0.5rem;
}

.wishlist-sharebox .share-facebook {
    border-radius: var(--button-rounding);
}

/**
 * Form elements
 */
button.btn {
    background: transparent;
    color: var(--color-text);
    padding: var(--button-py) var(--button-px);
    border-radius: var(--button-rounding);
}

button.btn-primary {
    color: var(--button-text-primary);
    background: var(--color-primary);
}

input.form-control {
    display: block;
    width: 100%;

    padding: var(--input-py) var(--input-px);
    background: var(--input-bg);
    border: var(--input-border);
    border-radius: var(--input-rounding);
    color: var(--color-text);
}

label + input.form-control {
    margin-bottom: 1rem;
}


/**
 * Rating
 */
.reviews-total svg {
    width: 1.5rem;
    height: 1.5rem;
}


/**
 * Login
 */

.login,
.register {
    max-width: 24rem;
    margin: 0 auto;
    padding: 0 1rem;
}

.login div,
.register div {
    width: 100% !important;
}

.login form,
.register form {
    margin-top: 3rem;
    text-align: left;
}

.login label,
.register label {
    display: block;
    margin-bottom: 0.5rem;
    text-align: left;
    font-size: 0.875rem;
}

.login label.cursor,
.register label.cursor {
    padding: 1rem 0;
}

.login label.cursor + label.cursor,
.register label.cursor + label.cursor {
    margin-left: 1rem;
}

.login label.cursor,
.register label.cursor,
.login label.cursor > input[type="radio"],
.register label.cursor > input[type="radio"] {
    display: inline-block;
    width: auto;
    cursor: pointer;
}

.login label.cursor > input[type="radio"],
.register label.cursor > input[type="radio"] {
    margin-right: .5rem;
    width: 1.5rem;
    height: 1.5rem;
    color: var(--color-primary);
    --tw-ring-color: var(--color-primary);
}

.login input[type="text"],
.login input[type="email"],
.login input[type="password"],
.register input[type="text"],
.register input[type="email"],
.register input[type="password"] {
    margin-bottom: 1rem;
}

.login .btn-inverse,
.register .btn-inverse,
.register hr + div > a[href] {
    margin: 1rem 0 2rem 0;
    background-color: var(--color-primary);
    color: #ffffff;
    font-weight: 600;
    padding: var(--input-py) var(--input-px);
    border: none;
    cursor: pointer;
    border-radius: var(--button-rounding);
    width: 100%;
}

.register hr + div a[href] {
    padding: 0.75rem 2rem;
}

.login .btn-inverse :hover,
.register .btn-inverse :hover {
    background-color: var(--color-text);
}

.login br,
.register br {
    display: none;
}

.login .btn-inverse:hover,
.register .btn-inverse:hover {
    background-color: var(--color-text);
}

.login hr,
.register hr {
    margin-bottom: 2rem;
}

.login hr + div,
.register hr + div {
    display: block;
}

.login hr + div > a,
.register hr + div > a[href] {
    display: block;
    margin-bottom: 1rem;
    font-size: 1rem !important;
    color: var(--color-primary);
}

.login hr + div > a:hover,
.register hr + div > a:hover {
    color: var(--color-text);
}

.login hr + div a.btn,
.register hr + div a[href] {
    display: block;
    background: transparent;
    font-size: 1rem !important;
    color: var(--color-primary);
    border: 1px solid var(--color-primary);
    border-radius: var(--button-rounding);
}

.login hr + div a.btn:hover,
.register hr + div a:hover {
    background: transparent;
    color: var(--color-text);
    border-color: var(--color-text);
}

.customerarea_login_message {
    margin-bottom: 2rem !important;
}


/**
 * Fix for theme previewer events
 */
.selected-content .pointer-events-none {
    pointer-events: auto;
} 

/**
 * Fix for image alignment
 */
img.fr-dib {
    margin: 5px auto
}

img.fr-dib.fr-fil {
    margin-left: 0;
}

img.fr-dib.fr-fir {
    margin-right: 0;
}


/* ==========================================================================
 * AD70 CUSTOM — praline box builder
 *
 * Everything from here to the end of the file is ours, not stock Lejon. It was
 * originally marked only with the word "Airlectra" in a bare comment -- the
 * agency that built the praline flow -- and later edits were appended with no
 * separation, so a diff against a stock theme could not tell the two apart.
 * Hence these headers.
 *
 * Styles for js/box-builder.js: the slot grid (.box-grid), the assortment
 * (.list-grid) and the SNABBTITT modal (#pralin-modal).
 *
 * CONTRACT WITH js/box-builder.js -- do not delete these
 * -----------------------------------------------------
 * The grid-cols-3 / grid-cols-4 / lg:grid-cols-6 rules below are hand-written
 * because the shipped Tailwind build does not include them. The builder clamps
 * its column datafields to 1-4 mobile and 1-6 desktop precisely because a value
 * outside that range names a class that does not exist, and the grid then
 * silently collapses to one column. See cols() in js/box-builder.js.
 * ======================================================================== */

.grid-cols-3 {
    grid-template-columns: repeat(3,minmax(0,1fr))
}

.grid-cols-4 {
    grid-template-columns: repeat(4,minmax(0,1fr))
}

@media (min-width: 1024px) {
    .lg\:grid-cols-6 {
        grid-template-columns: repeat(6,minmax(0,1fr))
    }
}

.box-grid, .list-grid {
    gap:1rem;
}

.box-grid .box {
    /*width:calc(25% - 1rem);*/
    aspect-ratio: 1 / 1;
    border:1px solid;
    background-color:#eee;
}

.box-grid .box:has(img:not([src=""])) {
    background-color:#fff;
}

/*
.list-grid .box {
    width:calc(25% - 1rem);
}
*/

.list-grid .box h4 {
    font-size: 16px;
    text-align: center;
}

.list-grid .box .btn {
    background-color:transparent;
    border:1px solid var(--color-primary);
    letter-spacing:0;
    transition:all 0.5s;
    text-align:center;
    padding:0.5rem;
}

.list-grid .box .btn:hover {
    background-color: var(--color-primary);
    color: var(--button-text-primary);
    cursor:pointer;
}

.list-img, .box-img {
    position:relative;
}

.list-grid .list-img-wrapper .list-img::before, .box-grid .box-img-wrapper .box-img::before {
    content: "";
    display: block;
    position: absolute;
    left: 0px;
    top: 0px;
    bottom: 0px;
    z-index: 9;
    width: 100%;
    opacity: 0;
    transition-property: opacity;
    transition-duration: 1s;
    transition-delay: 0s;
    background: rgba(0, 0, 0, 0.3);
}

.list-grid .list-img-wrapper:hover, .box-grid .box-img-wrapper:hover {
    cursor: pointer;
}

.list-grid .list-img-wrapper:hover .list-img::before, .box-grid .box-img-wrapper:hover .box-img::before {
    opacity: 1;
    background-position: center;
    background-repeat: no-repeat;
    margin: 0 auto;
    background-size: 50px;
}

.list-grid .list-img-wrapper:hover .list-img::before {
    background-image: url(https://s3.eu-west-1.amazonaws.com/storage.quickbutik.com/stores/83315t/files/add-icon-white.png) !important;
}

.box-img {
    height:0;
}

.box-grid .box-img-wrapper:hover .box-img {
    height:unset;
}

.box-grid .box-img-wrapper:hover .box-img::before {
    background-image: url(https://s3.eu-west-1.amazonaws.com/storage.quickbutik.com/stores/83315t/files/remove-icon-white.png) !important;
}

/* AD70 CUSTOM: one tap to remove a praline on touch devices.
 *
 * .box-img is the element js/box-builder.js keys its REMOVE branch off, and
 * the rule above gives it height ONLY on hover. iOS has no hover, so the
 * first tap merely applied the emulated :hover state and the second did the
 * actual removing -- reported from an iPhone, 2026-08-04.
 *
 * The assortment's .list-img is never collapsed this way, which is exactly
 * why ADDING a praline always took one tap and only removing took two.
 *
 * This is not new behaviour: height:unset is already what every slot gets on
 * hover, so touch devices simply get the known-good hovered geometry all the
 * time. Mouse and trackpad are untouched -- for them hover is free, so
 * removing has always been a single click.
 *
 * The dark scrim and the "-" icon stay hover-only on purpose. Showing them
 * permanently would cover the pralines the customer just chose. */
@media (hover: none) {
    .box-grid .box-img-wrapper .box-img {
        height: unset;
    }
}

#pralin-modal {
    display: none;
    position: fixed;
    z-index: 199;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgb(0,0,0);
    background-color: rgba(0,0,0,0.4);
}

#pralin-modal .modal-content {
    background-color: #fefefe;
    margin-top: 5rem;
    margin-left: auto;
    margin-right: auto;
    padding: 20px;
    border: 1px solid #888;
    width: 300px;
    max-width:80%;
}

@media (min-width:992px) {
    #pralin-modal .modal-content {
        width:600px;
    }
}

#modal-img {
    width:250px;
    margin: 0 auto;
}

#pralin-modal .modal-close {
    color: #aaa;
    float: right;
    font-size: 28px;
    font-weight: bold;
    line-height: 1;
    margin-top: -1rem;
}

#pralin-modal .modal-close:hover, #pralin-modal .modal-close:focus {
    color: black;
    text-decoration: none;
    cursor: pointer;
}

@media (min-width: 1024px) {
    .lg\:mt-16 {
        margin-top: 4rem;
    }
}

/* ==========================================================================
 * AD70 CUSTOM — disabled add-to-cart CTA
 *
 * On a box product the CTA stays disabled until the box is full and its
 * contents fit the plocklista property -- Alpine binds it to $store.box_full,
 * set by box_contents() in js/box-builder.js. Stock's hover styling would still
 * brighten it on hover, which reads as clickable, so both are pinned here.
 * ======================================================================== */

.cursor-pointer.cursor-not-allowed {
    cursor: not-allowed
}

.cursor-pointer.cursor-not-allowed.hover-opacity.opacity-20:hover {
    opacity:0.2;
}

/* ==========================================================================
 * AD70 CUSTOM — product gallery sizing
 *
 * "Mindre produktbild på desktop": the main image ran very tall on desktop.
 *
 * The thumbnails need !important because Swiper writes inline width/height onto
 * every slide as it lays them out; without it the squares get stretched back.
 * Related: _files/partials/product_images.mustache hardcodes object-cover on
 * these thumbnails, because stock's settings.productpage_thumbnails_crop
 * setting does NOT exist in our settings_list.json -- it is one of the 70
 * settings we are behind on. See docs/theme-comparison.md.
 *
 * (No Mustache braces in this comment on purpose. This file is .css.mustache
 * and the parser reads tags inside CSS comments too, so writing the section tag
 * out in full would register as an unclosed section and fail the pre-push
 * check. It did exactly that once already.)
 * ======================================================================== */

@media (min-width: 768px) {
    .products-swiper-main .swiper-slide img {
        max-height: 400px;
    }
}

/* Only the thumbnail is squared, so Swiper's own layout is left alone. */
.products-swiper-thumbs .swiper-slide {
    height: 8rem !important;   /* samma som h-32 */
    width: 8rem !important;    /* gör den kvadratisk */
    flex: 0 0 auto !important; /* hindrar Swiper från att töja den */
}

.products-swiper-thumbs .swiper-slide img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
}
/* ==========================================================================
 * AD70 CUSTOM — hero / banner legibility
 *
 * Startpage banner headings were hard to read against light photography. This
 * lifts the dark scrim slightly and puts white text with a drop shadow on top.
 *
 * FRAGILE — these selectors target STOCK MARKUP BY SHAPE
 * -----------------------------------------------------
 * There is no stable hook here: .bg-black.opacity-40 is a Tailwind utility pair
 * that happens to form the banner scrim, and a[aria-label] .flex.relative h2
 * describes the banner's structure rather than naming it. Both will stop
 * matching, or start matching something else, if Quickbutik reworks
 * _files/partials/start_banners.mustache -- which it already has: stock differs
 * from ours by 48 lines there (see docs/theme-comparison.md). Re-test the
 * startpage visually after any theme update.
 *
 * The overlay rule below was previously declared TWICE, at 0.3 and then 0.35.
 * Only the second took effect. Merged to one declaration on 2026-08-02, keeping
 * 0.35 -- the value that was actually live.
 * ======================================================================== */

.bg-black.opacity-40 {
    opacity: 0.35 !important;
}

a[aria-label] .flex.relative h2 {
    color: #ffffff !important;
    font-weight: 700 !important;
    text-shadow: 0 2px 10px rgba(0,0,0,0.75) !important;
}

a[aria-label] .flex.relative p,
a[aria-label] .flex.relative span {
    color: #ffffff !important;
    opacity: 1 !important;
    font-weight: 500 !important;
    text-shadow: 0 2px 8px rgba(0,0,0,0.8) !important;
}


/* ========================================================================
 * AD70 CUSTOM -- editorial typography and product cards
 *
 * Added 2026-08-04. Makes the theme read as high-end without touching any
 * markup. Pairs with the settings.json pass of the same date: Bodoni Moda
 * headings, white card background, no shadows, 4 per row, 16px base.
 *
 * FRAGILE -- two selectors target STOCK MARKUP BY SHAPE
 * ----------------------------------------------------
 * Same hazard as the banner rules above; neither has a stable hook.
 *   - li.mx-2 is how nav_top.mustache marks a TOP-LEVEL nav item. Dropdown
 *     children do not carry it, which is the only reason this does not leak
 *     into submenus. If that partial is reworked the nav silently loses its
 *     small caps.
 *   - .product h3.font-body is the product card title in
 *     partials/product_item.mustache. It is hardcoded font-body there, and
 *     .font-body outranks the h3 rule near the top of this file on
 *     specificity, so the headings-font SETTING cannot reach card titles at
 *     all. This rule is what puts them in the heading serif.
 * Re-check the header and any product list after a Quickbutik theme update.
 * ======================================================================== */

/* Nav in small caps. Also normalises the mixed casing that comes from how
   categories and pages are named in the admin -- "AKTUELLT" next to
   "Om oss" -- without renaming anything in the shop. */
#main-nav li.mx-2 > a,
#main-nav li.mx-2 > div > a {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.78rem;
}

/* Card titles in the headings serif at book weight. Reads as a name rather
   than a label; bold Bodoni at this size is too heavy. */
.product h3.font-body {
    font-family: 'Bodoni Moda',serif-serif;
    font-weight: 400;
    letter-spacing: 0.01em;
}

/* Slow zoom on the product image. Transform only, so it composites on the
   GPU. The second-image-on-hover swap uses opacity and is unaffected --
   when a second image exists both layers scale together, which is intended. */
.product .group img {
    transition: transform 0.6s ease;
}

.product .group:hover img {
    transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
    .product .group img,
    .product .group:hover img {
        transition: none;
        transform: none;
    }
}

/* Hairlines in the accent copper instead of grey. The !important is needed
   because every hr carries the opacity-10 utility inline in the markup, and
   copper at 10% is indistinguishable from grey at 10%. */
hr.border-foreground {
    border-color: var(--color-accent) !important;
    opacity: 0.3 !important;
}


/* ========================================================================
 * AD70 CUSTOM -- nav hover pill and active-page dot
 *
 * Added 2026-08-04, from ad70-header-spec.md sections 2 and 3. Replaces the
 * stock hover-opacity fade on top-level nav links with a rounded copper wash,
 * and marks the current page with a dot under its label -- the site had NO
 * active-page indication at all before this.
 *
 * No markup changed. The .active hook already exists: nav_top.mustache emits
 * it from the link's own current flag, and nothing in this stylesheet
 * targeted .active until now. Verified against live -- /praliner renders it
 * exactly once.
 *
 * FRAGILE -- reuses the shape-based li.mx-2 hook from the block above and
 * inherits its fragility for the same reason: mx-2 is how nav_top.mustache
 * marks a TOP-LEVEL item, and dropdown children do not carry it. The mobile
 * drawer puts .active on links WITHOUT mx-2, so it is deliberately untouched;
 * it sits on bg-body and would need different colours.
 *
 * WHY THE DOT SITS INSIDE THE LINK BOX RATHER THAN BELOW IT
 * ---------------------------------------------------------
 * nav_top.mustache wraps the whole menu in a div carrying overflow-y-auto.
 * Per CSS overflow rules a visible x-axis computes to auto when the y-axis is
 * not visible, so that wrapper CLIPS IN BOTH DIRECTIONS. A dot placed below
 * the link -- the obvious reading of the spec -- would be cut off, or would
 * add a scrollbar to the menu. It therefore lives in the link's own bottom
 * padding. That is also why EVERY top-level link gets padding-bottom here and
 * not just the active one: constant geometry means the current page does not
 * sit taller than its neighbours and the row does not shift as you navigate.
 * ======================================================================== */

#main-nav li.mx-2 > a,
#main-nav li.mx-2 > div > a {
    position: relative;
    border-radius: 999px;
    padding-bottom: 0.75rem;
    transition: background-color 200ms ease, color 200ms ease;
}

/* The wash carries its alpha as an 8-digit hex appended to the accent
   SETTING, so it tracks color_accent instead of pinning copper a second
   time. 2e = 18%. Deliberately header-agnostic: nav text sits at 8.8:1 on
   the light header and 10.5:1 on the dark one, so the block below can flip
   the header without these values needing to move. */
#main-nav li.mx-2 > a:hover,
#main-nav li.mx-2 > div > a:hover {
    background-color: #b2674d2e;
    opacity: 1;
}

/* Stronger than the hover wash (42 = 26%, text 8.1:1 light / 9.5:1 dark), and
   declared after it so the current page keeps the heavier pill on hover. */
#main-nav li.mx-2 > a.active,
#main-nav li.mx-2 > div > a.active {
    background-color: #b2674d42;
}

#main-nav li.mx-2 > a.active::after,
#main-nav li.mx-2 > div > a.active::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 0.2rem;
    transform: translateX(-50%);
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--color-accent);
    box-shadow: 0 0 0 3px #b2674d40;
}


/* ========================================================================
 * AD70 CUSTOM -- dark header and dark mobile panel
 *
 * Added 2026-08-04, from ad70-header-spec.md sections 1 and 4. Puts the
 * header and the mobile slide-out panel on the footer's dark tone, so the
 * page closes the way it opens.
 *
 * *** NOT READY FOR LIVE. THIS BLOCK IS ON BSF-dev2 FOR REVIEW ONLY. ***
 * The logo is a white "AD 70" panel plus the cursive "Choklad" rendered as
 * DARK INK ON TRANSPARENCY, and that script is unreadable on 2b2b2b. It
 * appears in BOTH places this block darkens -- header.mustache and
 * nav_mobile.mustache. A light logo variant must be uploaded in the admin
 * (assets are not workspace files) before any of this reaches customers.
 * Delete this whole block to revert; it is self-contained by design.
 *
 * WHY THIS IS CSS AND NOT A settings.json CHANGE
 * ----------------------------------------------
 * color_header_background feeds --bg-header, which is NOT header-only:
 * start_banners.mustache uses it for any banner whose use_navbar_background_
 * color is set, and SIX startpage elements have it set, four of them with
 * dark content text. Changing the setting would turn those six near-black
 * as well. Scoping to #main-nav leaves them alone.
 *
 * Both colours are pulled from the FOOTER variables rather than hardcoded,
 * so header and footer stay locked together -- which is the stated point of
 * the change -- and a future footer retone carries the header with it.
 *
 * The spec's note that the mobile panel inherits --bg-header is not correct:
 * the panel is bg-body, i.e. white, and needs its own rule. See below.
 * ======================================================================== */

#main-nav.bg-header {
    background-color: var(--bg-footer);
}

/* Scoped to .text-navbar, NOT to #main-nav. The mobile panel is a DESCENDANT
   of #main-nav, so colouring the header element would leak into it and fight
   the panel rules below. .text-navbar appears only on the two header nav
   elements, which is exactly the wanted reach. */
#main-nav .text-navbar {
    color: var(--color-footer);
}

/* Pill text, desktop. The spec's warm creme, a shade warmer than
   --color-footer. It lives in THIS block rather than with the pill rules
   above because it only works against a dark header -- on the light header
   it falls to 1.45:1. Reverting this block restores the inherited colour. */
#main-nav li.mx-2 > a:hover,
#main-nav li.mx-2 > div > a:hover,
#main-nav li.mx-2 > a.active,
#main-nav li.mx-2 > div > a.active {
    color: #f7e4d8;
}

/* ---- Mobile panel ---------------------------------------------------- */

/* The close X and all three levels of expand chevron draw with
   stroke="currentColor" and sit in divs rather than links, so the spec's
   rule on `a` never reaches them -- they would have stayed at --color-text,
   1.60:1 against this background. One inherited colour on the panel covers
   all of them. */
.navbar-menu > nav {
    background-color: var(--bg-footer);
    color: var(--color-footer);
}

/* .text-body pins its own colour, so inheritance does not reach the outline
   Settings button. Its border needs the same treatment; at 35% the outline
   reads as secondary next to the solid login CTA instead of shouting. */
.navbar-menu > nav .text-body {
    color: var(--color-footer);
}

.navbar-menu > nav .border-foreground {
    border-color: #f5f3f059;
}

/* Scoped to `ul a` so the login CTA and the Settings button in the footer of
   the panel keep their own button-rounding.
 *
 * The padding/margin pair is what keeps the dot off the pill's edge. The
 * anchors ship with `block py-3` and NO horizontal padding, so without this
 * the dot sat flush against the left edge of the tint with zero breathing
 * room -- reported from an iPhone, 2026-08-04. The padding insets the dot;
 * the smaller negative margin lets the pill bleed a little into the
 * container's px-6 gutter so the row still reads as a full-width band. Net
 * effect: dot moves 8px right AND gains 16px of space inside the pill.
 *
 * The margin is deliberately smaller than the gutter (8 < 24), so the pill
 * stays inside the container's padding box and cannot trigger the horizontal
 * clipping described below.
 *
 * This shop's mobile menu is currently FLAT -- 10 top-level links, no nested
 * ul, no dropdown-parent anchors. If child menu items are ever added, check
 * two things here: nested links inherit this indent (which would flatten the
 * pl-4 hierarchy), and a parent anchor is `flex flex-1` beside its chevron,
 * so the negative right margin would run the tint under it. */
.navbar-menu > nav ul a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-inline: 16px;
    margin-inline: -8px;
    border-radius: 8px;
    transition: background-color 200ms ease, color 200ms ease;
}

/* EVERY row carries the dot, transparent unless it is the current page, so
   the active row does not sit 16px to the right of its neighbours. It cannot
   be hung in the left gutter instead: the panel's list container carries
   overflow-y-auto, and a non-visible y-axis forces x to auto too, so
   anything outside the link box is clipped. Same trap as the desktop dot. */
.navbar-menu > nav ul a::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: transparent;
    flex-shrink: 0;
}

/* Also neutralises the stock hover:text-gray-900, which would otherwise put
   near-black text on this background. It never fires on touch, but it does
   on a narrow desktop window. */
.navbar-menu > nav ul a:hover {
    background-color: #b2674d2e;
    color: #f7e4d8;
}

.navbar-menu > nav ul a.active {
    background-color: #b2674d42;
    color: #f7e4d8;
}

.navbar-menu > nav ul a.active::before {
    background: var(--color-accent);
    box-shadow: 0 0 0 3px #b2674d40;
}


/* ========================================================================
 * AD70 CUSTOM -- tactile feedback and accent scrollbar
 *
 * Added 2026-08-04, from ad70-moderna-detaljer-spec.md sections 2 and 5.
 * Independent of the two nav blocks above and of the header tone; safe to
 * ship on its own.
 *
 * Both animations are wrapped by the prefers-reduced-motion guard at the end
 * of this block, matching the image hover zoom from the design pass.
 * ======================================================================== */

/* The spec names .add-to-cart-btn, which does not exist. The real hook is
   .qs-cart-submit, which is BOTH the main product-page button and the
   quick-add on a product card -- so one rule covers every add-to-cart in the
   shop. It is also a praline-flow selector: the category-2 CSS in
   _files/list.mustache hides these on the Praliner category. This rule only
   adds a transform on :active and cannot affect that. */
.qs-cart-submit {
    transition: transform 120ms ease;
}

.qs-cart-submit:active {
    transform: scale(0.96);
}

/* Cart badge entrance.
 *
 * PARTIAL BY CONSTRUCTION, and worth knowing before judging it: the spec asks
 * for a bounce on every successful add. The badge lives inside an Alpine
 * <template x-if="$store.cart.totalQuantity > 0"> in header.mustache, so the
 * element is CREATED when the cart goes from empty to non-empty -- which is
 * what makes a CSS animation fire, with no JavaScript. Going from 1 to 2 only
 * updates x-text on the existing node, so it does NOT re-run.
 *
 * So this animates the badge appearing, not every add. Covering every add
 * needs a JS class toggle on the add handler, which would mean a module and
 * tests under this project's standard. */
@keyframes ad70-cart-pop {
    0%   { transform: scale(0.4); opacity: 0; }
    60%  { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

.cart-bubble {
    animation: ad70-cart-pop 350ms ease;
}

/* Scrollbar in the accent copper.
 *
 * OVERRIDES A STOCK RULE -- the theme already styles this at the "Browser
 * scrollbar (Webkit)" block earlier in this file: body::-webkit-scrollbar at
 * 4px with a --color-primary thumb. These selectors are deliberately
 * body-prefixed to match its specificity and win on source order. A bare
 * ::-webkit-scrollbar would LOSE to it on the page scrollbar while leaking
 * into every inner scroll container instead -- the cart drawer, the modals,
 * and the two nav wrappers -- which is the opposite of what is wanted.
 *
 * Scoped to the page for the same reason: this is the spec's "high finish"
 * detail on the main bar, not a restyle of every scrollable box.
 *
 * Two syntaxes, deliberately: ::-webkit-scrollbar is Chrome/Safari/Edge only,
 * scrollbar-color is the standard property Firefox uses. Note this widens the
 * bar from the stock 4px to 10px, which is the spec's value. */
body::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

body::-webkit-scrollbar-track {
    background: var(--input-bg);
}

body::-webkit-scrollbar-thumb {
    width: 10px;
    background-color: var(--color-accent);
    border-radius: 999px;
}

html {
    scrollbar-color: var(--color-accent) var(--input-bg);
    scrollbar-width: thin;
}

@media (prefers-reduced-motion: reduce) {
    .qs-cart-submit,
    .qs-cart-submit:active {
        transition: none;
        transform: none;
    }

    .cart-bubble {
        animation: none;
    }
}