/*
 * Theme base layer.
 *
 * The design system's own reset lives in tokens/base.css and is loaded before
 * this file: box-sizing, body font, heading family/weight, link colour, image
 * defaults, ::selection and the ds-spin / ds-shimmer / ds-rise keyframes. Nothing
 * here repeats it — this file adds the element defaults the reset leaves open,
 * the layout utilities and the WordPress-specific glue.
 *
 * Never hard-code a value that exists as a token.
 *
 * Contents
 *   1. Breakpoint variables   — every media query in the theme lives here
 *   2. Element defaults       — expressed through the composite type roles
 *   3. Layout utilities       — container, section rhythm, grid tracks
 *   4. Focus                  — the single global rule
 *   5. WordPress glue         — skip link, screen-reader text, admin bar
 */

/* ══ 1. Breakpoints ══════════════════════════════════════════════════════════
 *
 * mobile 320–767 · tablet 768–1023 · md 1024–1439 · lg 1440+
 *
 * The four ranges are declared exactly once, here, as custom properties. Every
 * responsive value in the theme — gutters, rhythm, grid tracks — is a variable
 * resolved in these blocks, so components and screens never write a media query
 * of their own. Values are taken verbatim from the handoff breakpoint table and
 * from the `g:` maps in prototype/kit/bp.js.
 */

:root {
	/*
	 * Side gutter. theme.json points its root padding at this custom property,
	 * because theme.json itself cannot express media queries. 16 / 20 / 20 / 20.
	 */
	--ds-gutter: var(--space-5); /* 16px */

	/* Gap between grid tracks — bp.js `gutter`. 12 / 16 / 20 / 20. */
	--ds-grid-gutter: var(--space-4); /* 12px */

	/* Vertical rhythm between page sections. 40 / 48 / 64 / 80. */
	--ds-section-rhythm: var(--space-9); /* 40px */

	/* Grid tracks — bp.js `g`, mobile column. */
	--dl-track-g4: 1fr 1fr;
	--dl-track-g3: 1fr;
	--dl-track-cards: 1fr 1fr;
	--dl-track-hero: 1fr;
	--dl-track-product: 1fr;
	--dl-track-rail: 1fr;
	--dl-track-sidebar: 1fr;
	--dl-track-form2: 1fr;
	--dl-track-form3: 1fr;
	--dl-track-usp: 1fr 1fr;
	--dl-track-footer: 1fr;
	--dl-track-blog: 1fr;
	--dl-track-blog-rail: 1fr;
	--dl-track-wish: 1fr;
	--dl-track-acct: 1fr;
	/*
	 * bp.js verbatim: one column. The status and total sit in implicit
	 * columns placed by --dl-order-status-area / --dl-order-total-area, and
	 * grid resolves the fr against the implicit tracks too, so the row
	 * renders as it did with the second track spelled out.
	 */
	--dl-track-orders: 1fr;
	--dl-track-stats: 1fr 1fr;

	/*
	 * Product rows — the front page and the related-products row.
	 *
	 * On mobile these are not wrapped grids but horizontally scrolling
	 * carousels with snap points and fixed 200px cards, bleeding into the
	 * gutter on both sides; from tablet up they are the same g4 grid as
	 * everything else. One markup tree, seven properties.
	 */
	--dl-row-display: flex;
	--dl-row-columns: none;
	--dl-row-overflow: auto;
	--dl-row-snap: x mandatory;
	--dl-row-item: 0 0 200px; /* no token — the carousel card width as drawn */
	--dl-row-bleed: calc(var(--ds-gutter) * -1);
	--dl-row-pad-block-end: var(--space-3); /* room for the card's own shadow */

	/*
	 * Section header — the eyebrow, the h2 and the action slot.
	 *
	 * The mobile variant is not a narrowed desktop one: the title drops a step
	 * down the type scale, and the two gaps around it tighten. Every screen in
	 * the shop opens its rows with this header, so the four properties are read
	 * far more often than they are written.
	 */
	--dl-section-head-gap: var(--space-4); /* 12px between the text and the action */
	--dl-section-head-space: var(--space-5); /* 16px below the header */
	--dl-section-head-eyebrow-gap: 4px; /* no token — optical, under the 11px line */
	--dl-section-head-title-font: var(--weight-light) var(--text-2xl) / 1.25 var(--font-display);

	/*
	 * Hero. The handoff draws two heroes rather than one that reflows: the
	 * desktop pair of columns with the finder card below them, and a stacked
	 * mobile screen with full-width buttons and the finder card pulled up over
	 * the gradient's bottom edge. This block is the whole difference between
	 * them — there is one markup tree, in inc/hero.php.
	 */
	--dl-hero-pad-block-start: var(--space-8); /* 32px */
	--dl-hero-pad-block-end: var(--space-7); /* 24px — the band with no finder in it */
	--dl-hero-gap: var(--space-6); /* 20px between the stacked text and plate */
	--dl-hero-text-gap: var(--space-4); /* 12px */
	--dl-hero-title-font: var(--weight-extralight) var(--text-4xl) / 1.1 var(--font-display);
	--dl-hero-title-max: none;
	--dl-hero-lead-size: var(--text-base);
	--dl-hero-lead-max: none;
	--dl-hero-actions-gap: var(--space-4); /* 12px */
	--dl-hero-action-width: 100%; /* full-width buttons, as MHome draws the primary */
	--dl-hero-media-radius: var(--radius-xl);
	--dl-hero-media-shadow: var(--shadow-0);

	/*
	 * The finder card. On mobile it straddles the bottom edge of the gradient:
	 * the negative bottom margin pulls the band — and the hairline that closes
	 * it — up past the card, so the card overlaps the boundary by 20px. On
	 * desktop the pull is zero and the card sits inside the wash, 40px below the
	 * columns, which is where the prototype puts it.
	 */
	--dl-hero-finder-gap: 4px; /* no token — what is left of MHome's 24px once the card is pulled up */
	--dl-hero-finder-pull: -20px; /* no token — the overlap as drawn */
	--dl-hero-band-pad-finder: 0px; /* the card, not the padding, closes the band */
	--dl-hero-overhang: 20px; /* what the card hangs below the wash, given back */

	/*
	 * VehiclePicker. Mobile stacks the three controls full-width, which is one
	 * track; desktop is the prototype's `1fr 1fr auto` with the button sized by
	 * its label.
	 */
	--dl-vehicle-pad: var(--space-5); /* 16px */
	--dl-vehicle-cols: 1fr;
	--dl-vehicle-gap: var(--space-4); /* 12px */
	--dl-vehicle-head-space: var(--space-5); /* 16px */

	/* Promo tiles. The plate ratio and the radius do not change; the inset does. */
	--dl-promo-pad: var(--space-5); /* 16px */

	/*
	 * Blog teasers. Mobile turns the card on its side — a 104px image rail with
	 * the date and the title beside it — and drops the excerpt and the "Les mer"
	 * line, which is what the handoff draws and what fits a 390px column.
	 */
	--dl-post-card-direction: row;
	--dl-post-card-plate-width: 104px; /* no token — the image rail as drawn */
	--dl-post-card-plate-ratio: auto;
	--dl-post-card-pad: var(--space-5); /* 16px */
	--dl-post-card-title-font: var(--weight-regular) var(--text-base) / 1.3 var(--font-display);
	--dl-post-card-excerpt-display: none;
	--dl-post-card-more-display: none;

	/*
	 * The article screen. Mobile and tablet are one column: the rail drops below
	 * the body and stops sticking, because there is nothing beside it to stay
	 * level with.
	 *
	 * The table of contents goes with it — hidden, not moved inline. A list of
	 * jump links stacked above a 720px column of copy is a screenful the reader
	 * has to scroll past to reach the article, and every entry in it is a heading
	 * they will meet anyway a moment later. The mention card is a different
	 * thing — it points somewhere the article does not go — so it stays at every
	 * width.
	 *
	 * This group is the reading column's, not the article's alone.
	 * `templates/page.html` renders the same head and the same 720px body —
	 * without the rail, the contents or the share row — so a static page takes
	 * these values too. The names stay `--dl-article-*`: the article is where the
	 * column is fully expressed, and renaming a group that four breakpoints and
	 * § 9 of screens.css already reference would be churn for a synonym.
	 */
	--dl-article-gap: var(--space-8); /* 32px between the body and the rail below it */
	--dl-article-head-space: var(--space-8); /* 32px under the head */
	--dl-article-rail-position: static;
	--dl-article-rail-top: auto;
	--dl-article-toc-display: none;

	/*
	 * How far a list in running copy is pushed in to make room for its markers.
	 * On mobile the copy runs to a 16px gutter and a marker outside the column
	 * would sit on the screen edge, so the list is indented. From 1024px up the
	 * column has room on both sides: the markers hang in it and the text of a
	 * list lines up with the paragraphs above and below it, which is the point.
	 */
	--dl-prose-list-indent: var(--space-6); /* 20px */

	/*
	 * Header — bp.js `header: mobile | compact | full`.
	 *
	 * The header is the one piece of chrome that changes structure rather than
	 * re-flowing, and it still ships as a single markup tree: these properties
	 * are the whole difference between the three variants. `mobile` is here,
	 * `compact` in the 768 block, `full` in the 1024 one.
	 */
	--dl-header-pad-block: 10px; /* no token — the mobile bar is tighter than the scale */
	--dl-header-gap: var(--space-2); /* 4px */
	--dl-header-row-gap: 10px; /* no token — pairs with --dl-header-pad-block */
	--dl-header-action-size: 44px; /* no token — the handoff's hit-target floor */
	--dl-header-logo-w: 118px;
	--dl-header-menu-display: inline-flex;
	/* The hamburger is the last icon on the bar, so the gap before it has to be
	   the gap *between icons* rather than the bar's own. Here the two are the
	   same 4px and nothing is owed; from 768px up the bar opens and this pulls
	   the pair back together. */
	--dl-header-actions-margin-end: 0px;
	--dl-header-account-display: none; /* the drawer carries the account entry */
	--dl-header-search-flex: 1 0 100%; /* wraps to a row of its own */
	--dl-header-search-order: 1; /* dropped below the actions, onto its own row */
	--dl-header-search-max: none;
	--dl-header-search-pad-end: var(--space-5); /* no submit button to leave room for */
	--dl-header-search-submit: none;
	/* FiboSearch draws its button *inside* the input rather than beside it, so
	   the room is made by the caret's own padding — see assets/css/fibosearch.css. */
	--dl-fibo-input-pad-end: var(--space-5);
	--dl-topbar-full-display: none; /* only phone and the shipping note survive */

	/* Campaign notice. The handoff drops the «Kampanje» label below `full` and
	   tightens the band with it — the message is what matters on a phone, and
	   the eyebrow is the first thing a narrow row can spend. */
	--dl-promo-label-display: none;
	--dl-promo-gap: var(--space-3); /* 8px */
	--dl-promo-pad-block: var(--space-3); /* 8px */

	/* The department bar exists only on `full`; below it the drawer carries the
	   catalogue. The markup is rendered at every width — hiding it here rather
	   than in PHP keeps the one-markup-tree rule and the page cache honest. */
	--dl-mainnav-display: none;

	/*
	 * How tall the sticky header is, and therefore where anything else that
	 * sticks has to start. assets/js/sticky.js measures the header and rewrites
	 * this on :root, so the value below is only what the first paint — and a
	 * page with the script blocked — uses: the mobile bar's own parts added up
	 * (topbar 36 + 10 + 44 + 10 + the search row 40 + 10), rounded up rather than
	 * down, because a bar that starts too low leaves a gap and a bar that starts
	 * too high hides behind the header.
	 */
	--dl-header-h: 150px;

	/*
	 * Catalogue — the category, tag, attribute and shop archives.
	 *
	 * Below 1024px the sidebar's contents move into the right-hand drawer and
	 * the controls become a sticky bar under the title: the filter button, the
	 * count and the sort select on one row, with the active-filter chips in a
	 * row of their own below. From 1024px up the bar is `display: contents` and
	 * its three children become cells of the head's grid — see section 3 of
	 * screens.css, which is where the two shapes are one markup tree.
	 */
	--dl-catalog-gap: var(--space-6); /* 20px — nothing is beside the grid yet */
	--dl-catalog-sidebar-display: none; /* the drawer carries it below 1024 */
	--dl-catalog-header-space: var(--space-6); /* 20px under the title block */
	--dl-catalog-title-font: var(--weight-light) var(--text-3xl) / 1.2 var(--font-display);
	/*
	 * The head is `display: contents` here so the bar's containing block is the
	 * whole content column: a sticky element only travels inside its parent's
	 * box, and a head that is two rows tall would let the bar scroll away after
	 * 40 pixels. The two rows carry their own bottom margins instead of the
	 * head's gap.
	 */
	--dl-catalog-head-display: contents;
	--dl-catalog-head-cols: 1fr;
	--dl-catalog-head-gap: 0px;
	--dl-catalog-head-space: 0px;
	--dl-catalog-bar-space: var(--space-5); /* 16px under the sticky bar */
	--dl-catalog-tags-space: var(--space-5); /* 16px under the chips */
	--dl-catalog-bar-display: flex;
	--dl-catalog-bar-position: sticky;
	--dl-catalog-bar-pad: 10px var(--ds-gutter); /* no token — pairs with the header's own bar */
	--dl-catalog-bar-bleed: calc(var(--ds-gutter) * -1); /* runs to the screen edge */
	--dl-catalog-bar-border: var(--border-width) solid var(--border-subtle);
	--dl-catalog-bar-bg: var(--surface-page);
	--dl-catalog-filter-btn-display: inline-flex;
	--dl-catalog-sort-flex: 1; /* fills what the button leaves */
	--dl-catalog-sort-width: auto;

	/* Which cell of the head each control takes. `auto` while the bar is a flex
	   row of its own and only the chips are a grid item. */
	--dl-catalog-count-col: auto;
	--dl-catalog-tags-col: auto;
	--dl-catalog-sort-col: auto;
	--dl-catalog-head-row: auto;
	--dl-catalog-pagination-space: var(--space-8); /* 32px above the pagination */

	/*
	 * Søk — the product search results.
	 *
	 * Everything else on the screen is the catalogue's, above. What is its own is
	 * the row of matching categories, and the row is where the two shapes differ:
	 * a scrolling row of chips on mobile, the g4 grid of CategoryTiles from 768px
	 * up. The chip is the same tile with its plate and its arrow taken away — one
	 * markup tree, eleven properties.
	 */
	--dl-search-count-space: var(--space-3); /* 8px under the title, as drawn */
	--dl-search-alert-space: var(--space-6); /* 20px under the alert */
	--dl-search-cats-space: var(--space-7); /* 24px under the category row */
	--dl-search-cat-cols: none; /* one row of max-content tracks, not a grid of four */
	--dl-search-cat-flow: column;
	--dl-search-cat-auto: max-content;
	--dl-search-cat-overflow: auto;
	--dl-search-cat-bleed: calc(var(--ds-gutter) * -1); /* scrolls to the screen edge */
	--dl-search-cat-plate: none; /* a chip has no image */
	--dl-search-cat-meta-display: none; /* and no arrow */
	--dl-search-cat-radius: var(--radius-pill);
	--dl-search-cat-foot-pad: var(--space-3) var(--space-5);
	--dl-search-cat-label-font: var(--type-small);
	--dl-search-cat-label-wrap: nowrap;
	--dl-search-sort-width: auto; /* the sort fills what the row leaves */

	/*
	 * USP strip. The pill and the two type roles shrink on mobile — 40/19 and
	 * body-strong become 34/16 and 14px — which is the whole difference between
	 * the two variants the handoff draws.
	 */
	--dl-usp-pad-block: var(--space-8); /* 32px */
	--dl-usp-gap: var(--space-4); /* 12px — the mobile grid gap */
	--dl-usp-item-gap: 10px; /* no token — optical, between --space-3 and --space-4 */
	--dl-usp-pill-size: 34px; /* no token — the pill diameter as drawn */
	--dl-usp-glyph-size: 16px;
	--dl-usp-title-font: var(--weight-medium) var(--text-sm) / 1.2 var(--font-body);
	--dl-usp-text-font: var(--type-caption);

	/*
	 * Footer. Mobile is a shorter footer, not a narrowed one: the blurb, the
	 * category column and the column headings are gone, and the copyright reads
	 * differently. Each of those is one property here rather than a second
	 * markup tree — see section 8 of chrome.css.
	 *
	 * The contact column is the one place the theme goes further than the
	 * handoff, which kept only the e-mail line on mobile: the phone number, the
	 * company name, the address and the organisation number are shown at every
	 * width. They are the details a customer looks for on a phone, and a
	 * Norwegian shop is expected to state them.
	 */
	--dl-footer-pad-block-start: var(--space-9); /* 40px */
	--dl-footer-pad-block-end: var(--space-8); /* 32px */
	--dl-footer-gap: var(--space-5); /* 16px between the stacked pieces */
	--dl-footer-logo-w: 130px;
	--dl-footer-brand-display: contents; /* the brand's children join the one column */
	--dl-footer-blurb-display: none;
	--dl-footer-heading-display: none;
	--dl-footer-categories-display: none;
	--dl-footer-mail-icon-display: inline-block;
	--dl-footer-copy-full-display: none;
	--dl-footer-copy-short-display: inline;

	/* Source order is brand · kategorier · informasjon · kontakt; mobile wants
	   logo · informasjon · e-post · betaling, so three items are reordered. */
	--dl-footer-order-logo: 1;
	--dl-footer-order-information: 2;
	--dl-footer-order-contact: 3;
	--dl-footer-order-pay: 4;

	/*
	 * The bottom bar is mobile only. Its height is a variable rather than a
	 * literal because three other things read it: the padding that keeps page
	 * content clear of it, StickyBuyBar, which pins directly above it on the
	 * product page, and the toast region, which has to clear both.
	 */
	--dl-bottom-nav-display: grid;
	--dl-bottom-nav-h: 64px; /* no token — the bar height in the handoff */
	--dl-bottom-nav-space: calc(var(--dl-bottom-nav-h) + env(safe-area-inset-bottom));

	/*
	 * Produkt — the single product screen.
	 *
	 * The `product` track is the one grid in the theme that does not widen at
	 * 768px: bp.js gives tablet a single column too, because 834px split into a
	 * gallery and a buy box leaves neither of them usable. So the two-column
	 * shape appears at 1024 and the values below are the stacked one.
	 */
	--dl-product-gap: var(--space-7); /* 24px between the stacked gallery and buy box */
	--dl-product-head-space: var(--space-5); /* 16px under the breadcrumb */
	--dl-product-title-font: var(--weight-light) var(--text-2xl) / 1.25 var(--font-display);
	--dl-buybox-gap: var(--space-5); /* 16px between the pieces of the buy box */
	--dl-buybox-pad: 0px;
	--dl-buybox-wishlist-display: none; /* the plate carries it below 1024 */

	/*
	 * Gallery. Mobile is an edge-to-edge --neutral-50 plate with a dot pager;
	 * from 1024px up it is a white card with a 68px thumbnail rail beside it.
	 * Both are the same markup — a scroll-snapping stage, a rail and a set of
	 * dots — with one of the two controls `display: none` at any width, so only
	 * ever one of them is in the tab order.
	 */
	--dl-gallery-display: block;
	--dl-gallery-gap: 0px;
	--dl-gallery-max: none;
	--dl-gallery-bleed: calc(var(--ds-gutter) * -1); /* runs to the screen edge */
	--dl-gallery-frame-bg: var(--neutral-50);
	--dl-gallery-frame-border: 0;
	--dl-gallery-frame-radius: 0px;
	--dl-gallery-rail-display: none;
	--dl-gallery-plate-max: none; /* the frame is the column's width below 1024 */
	--dl-gallery-rail-max: none; /* there is no rail below 1024 */
	--dl-gallery-container: normal; /* the rail's cap needs a query container; only desktop has one */
	--dl-gallery-thumb-size: 68px; /* no token — the chip as drawn; the rail's cap reads it back */
	--dl-gallery-dots-display: flex;
	--dl-gallery-wishlist-display: inline-flex;
	--dl-gallery-inset: 14px; /* no token — the badge and heart inset as drawn */
	--dl-gallery-dot-size: 6px; /* no token — the pager dot as drawn */
	--dl-gallery-dot-active: 18px; /* no token — what the active one stretches to */
	--dl-gallery-zoom: 1; /* no hover, no zoom — see --dl-hover-reveal */

	/*
	 * Product information. Below 1024px the header list is `display: contents`,
	 * so the headers drop into the same column as the panels and `order`
	 * interleaves them into an accordion; from 1024px up the container is a plain
	 * block, `order` stops applying and the list is the tab strip. One markup
	 * tree, one set of panels — see woocommerce/single-product/tabs/tabs.php.
	 */
	--dl-prodinfo-space: var(--space-9); /* 40px above the block */
	--dl-prodinfo-display: flex;
	--dl-prodinfo-list-display: contents;
	--dl-prodinfo-border: var(--border-width) solid var(--border-subtle);
	--dl-prodinfo-radius: var(--radius-lg);
	--dl-prodinfo-overflow: hidden;
	/* The card is as wide as the column; the measure is imposed at md — see there. */
	--dl-prodinfo-max: none;
	--dl-prodinfo-tab-pad: var(--space-5) var(--space-6);
	--dl-prodinfo-tab-font: var(--weight-regular) var(--text-base) / 1.35 var(--font-display);
	--dl-prodinfo-tab-gap: 0px;
	--dl-prodinfo-tab-hover-bg: var(--surface-page);
	/* The hairline between accordion rows; the strip has none to sit on here. */
	--dl-prodinfo-row-rule: var(--border-width) solid var(--border-subtle);
	--dl-prodinfo-list-rule: 0;
	--dl-prodinfo-chevron-display: inline-block;
	--dl-prodinfo-panel-pad: 0 var(--space-6) var(--space-6);
	--dl-prodinfo-panel-max: none;
	--dl-prodinfo-spec-label-width: auto;
	/* The label column carries its own weight from 1024px up; here the accordion
	   row is narrow enough that colour alone separates the two cells. */
	--dl-spec-label-weight: var(--weight-regular);

	/*
	 * The review form. Name and e-mail share a row where there is room for two;
	 * the rating and the review itself never do — one is a short control, the
	 * other is the point. The form is one flex container either way: here it is
	 * a column and every field is full width, and from 768px the flow wraps and
	 * the two short fields take half the row less the gap.
	 */
	--dl-review-form-flow: column;
	--dl-review-form-half: 100%;

	/*
	 * StickyBuyBar. Mobile and tablet only, pinned above the BottomNav — which is
	 * why it starts from --dl-bottom-nav-space rather than from 0.
	 *
	 * The space it takes is reserved by theme.json's root bottom padding at every
	 * scroll position, not created when the bar appears, so revealing it shifts
	 * nothing. --dl-buybar-space is 0 everywhere except a product page, where
	 * screens.css sets it; both collapse to 0px from 1024px up along with the bar.
	 */
	--dl-buybar-display: flex;
	--dl-buybar-h: 72px; /* no token — the bar height in the handoff */
	--dl-buybar-space: 0px;

	/*
	 * Toast. Full width between 12px insets on mobile, a 340px card in the
	 * bottom-right corner from tablet up — the handoff's two placements.
	 *
	 * The distance from the bottom is not a literal: the handoff's 78px is the
	 * BottomNav's 64px plus 14, and on a product page the StickyBuyBar is
	 * between them too. Adding the two spaces that are already declared above
	 * keeps the toast off both without a third number to keep in step, and it
	 * collapses to the plain gutter where neither bar exists.
	 */
	--dl-toast-inset: 12px; /* no token — the handoff's mobile side inset */
	--dl-toast-left: var(--dl-toast-inset);
	--dl-toast-right: var(--dl-toast-inset);
	--dl-toast-w: auto;
	--dl-toast-gap: 14px; /* no token — what 78px is, above a 64px bar */
	--dl-toast-bottom: calc(
		var(--dl-bottom-nav-space) + var(--dl-buybar-space) + var(--dl-toast-gap)
	);

	/*
	 * The chat bubble (ihumbak-chat) is a fixed 50/60px circle in the
	 * bottom-right corner at z-index 9999, so it sits over whatever the theme
	 * pins there. Below 768px that is the BottomNav's "Konto" tab (#26). Its
	 * offset is derived rather than typed, for the same reason the toast's is:
	 * the two bar heights are already declared, and a third number would drift
	 * out of step with them.
	 */
	--dl-chat-inset: 10px; /* no token — the plugin's own mobile inset */
	--dl-chat-bottom: calc(
		var(--dl-bottom-nav-space) + var(--dl-buybar-space) + var(--dl-chat-inset)
	);

	/*
	 * MiniCart. The drawer is desktop only — below 1024px the header's cart
	 * button navigates to the cart page instead — and a `<dialog>` that is never
	 * opened is already `display: none`. This is the belt to that braces: if
	 * anything ever calls showModal() at a width that has no mini-cart, nothing
	 * appears.
	 */
	--dl-minicart-display: none;

	/*
	 * Handlekurv — the cart screen and the CartLine in it.
	 *
	 * Two shapes, and they part company at different widths: the *line* becomes
	 * the wide five-column row at 768px, where there is room for the quantity and
	 * the line total beside the title, while the *rail* only appears at 1024px,
	 * because bp.js gives tablet `rail: stack`. Below 768 the line is the
	 * handoff's tighter MCart variant — a 72px plate, the line total under the
	 * title and the stepper and the bin on a row of their own.
	 *
	 * One markup tree either way: the areas below are what move.
	 */
	--dl-cart-gap: var(--space-5); /* 16px between the lines card and the totals card */
	--dl-cart-steps-space: var(--space-6); /* 20px under CheckoutSteps */
	--dl-cart-title-space: var(--space-6); /* 20px under the h1 */
	--dl-cart-title-font: var(--weight-light) var(--text-3xl) / 1.2 var(--font-display);
	--dl-cart-card-pad-inline: var(--space-5); /* 16px — the card's side padding */
	--dl-cart-actions-pad: var(--space-5) 0; /* the ghost row under the lines */
	--dl-cart-actions-wrap: wrap;

	--dl-cartline-plate: 72px; /* no token — the compact thumbnail as drawn */
	--dl-cartline-cols: var(--dl-cartline-plate) 1fr auto;
	--dl-cartline-areas:
		'plate info info'
		'plate price price'
		'plate qty remove';
	--dl-cartline-align: start;
	--dl-cartline-pad-block: var(--space-5); /* 16px */
	--dl-cartline-gap: var(--space-4); /* 12px */
	--dl-cartline-row-gap: 10px; /* no token — between the stacked halves of a line */
	--dl-cartline-price-align: start;
	--dl-cartline-price-width: auto;
	--dl-cartline-unit-display: none; /* the compact line shows the line total only */

	--dl-summary-position: static;
	--dl-summary-top: auto;

	/*
	 * Kasse — «Ett skjema, alt synlig». The same rail as the cart's, so
	 * --dl-cart-gap, the title font and the sticky pair above are reused rather
	 * than duplicated: the two screens are one layout with different content in
	 * the first column.
	 *
	 * The checkout's own values are the rhythm between the four flat sections,
	 * the two tile grids and the address track. The numbered-card pair below
	 * (--dl-checkout-block-*) is kept because the *confirmation* screen and Min
	 * konto still draw cards with it — .dl-checkout__overview, .dl-order and
	 * .dl-login — even though the form itself no longer has numbered blocks.
	 */
	--dl-checkout-block-pad: var(--space-6); /* 20px */
	--dl-checkout-block-gap: var(--space-4); /* 12px — cards are stacked */
	--dl-checkout-block-head-gap: var(--space-5); /* 16px under the block heading */
	--dl-checkout-step-size: 24px; /* no token — the pill as drawn on mobile */
	--dl-checkout-block-title-font: var(--type-h4);
	--dl-checkout-field-gap: var(--space-4); /* 12px between fields */
	--dl-checkout-done-pad: var(--space-8) var(--space-6);

	--dl-checkout-section-gap: var(--space-7); /* 24px between the flat sections */
	--dl-checkout-head-gap: var(--space-5); /* 16px under a section's heading */
	--dl-checkout-rail-pad: var(--space-6); /* 20px inside the «Din ordre» card */
	--dl-checkout-rail-row-gap: var(--space-3); /* 8px — the rail reads as a block */
	--dl-checkout-title-font: var(--weight-light) var(--text-2xl) / 1.2 var(--font-display);
	--dl-track-address: 1fr 1fr; /* Postnummer | Poststed, the street across */
	--dl-checkout-tiles-ship: 1fr;
	--dl-checkout-tiles-pay: 1fr 1fr;

	/*
	 * Min konto (#21).
	 *
	 * The design draws two different screens and this is one document. Below
	 * 1024px there is no sidebar: `--dl-acct-side-display: contents` drops the
	 * card's box, and the three orders below put the identity first, the
	 * endpoint's content second and the menu last — an avatar header, the
	 * screen, then a full-width chevron list, which is what MAccount draws.
	 */
	--dl-acct-side-display: contents;
	--dl-acct-side-position: static;
	--dl-acct-side-top: auto;
	--dl-acct-gap: var(--space-6); /* 20px between the stacked parts */
	--dl-acct-id-order: 1;
	--dl-acct-main-order: 2;
	--dl-acct-menu-order: 3;
	--dl-acct-id-pad: 0;
	--dl-acct-id-gap: 14px; /* no token */
	--dl-acct-avatar-size: 48px; /* no token — MAccount's larger monogram */
	--dl-acct-avatar-font: var(--weight-medium) var(--text-lg) / 1 var(--font-display);
	--dl-acct-name-font: var(--type-h3);

	/* The menu as a list of cards, each its own tappable row. */
	--dl-acct-menu-gap: 2px; /* no token */
	--dl-acct-menu-row-bg: var(--surface-card);
	--dl-acct-menu-row-pad: 14px var(--space-5); /* 14px — the 44px hit target */
	--dl-acct-menu-row-radius: var(--radius-md);
	--dl-acct-menu-chevron: inline-flex;
	--dl-acct-menu-rule-display: none;

	/* The stat card: the icon over the number, centred. */
	--dl-acct-stat-pad: var(--space-4);
	--dl-acct-stat-direction: column;
	--dl-acct-stat-align: center;
	--dl-acct-stat-gap: 4px; /* no token */
	--dl-acct-stat-icon-size: auto;
	--dl-acct-stat-icon-bg: transparent;
	--dl-acct-stat-icon-color: var(--brand);
	--dl-acct-stat-value-font: var(--weight-medium) var(--text-xl) / 1.2 var(--font-display);

	/*
	 * OrderRow. Two columns rather than five, so the row reads as MAccount draws
	 * it: the order number over its date on the left, the badge over the total on
	 * the right, and «Se ordre» across the foot. Every cell is placed here rather
	 * than left to flow, because the source order is the desktop table's.
	 */
	--dl-order-head-display: none;
	--dl-order-row-gap: var(--space-2);
	--dl-order-id-area: 1 / 1 / 2 / 2;
	--dl-order-date-area: 2 / 1 / 3 / 2;
	--dl-order-status-area: 1 / 2 / 2 / 3;
	--dl-order-total-area: 2 / 2 / 3 / 3;
	--dl-order-action-area: 3 / 1 / 4 / 3;
	--dl-order-cell-justify: end;
	--dl-order-cell-align: end;
	--dl-order-action-justify: stretch;
	--dl-order-action-width: 100%;
}

@media (min-width: 768px) {
	:root {
		--ds-gutter: var(--space-6); /* 20px */
		--ds-grid-gutter: var(--space-5); /* 16px */
		--ds-section-rhythm: var(--space-10); /* 48px */

		/* bp.js `tablet.g`. Keys absent from the tablet override inherit the
		   desktop defaults, so form2 / form3 / orders / stats are set here. */
		--dl-track-g4: repeat(2, 1fr);
		--dl-track-g3: repeat(2, 1fr);
		--dl-track-cards: repeat(2, 1fr);
		--dl-track-hero: 1fr 1fr;
		--dl-track-product: 1fr;
		--dl-track-rail: 1fr;
		--dl-track-sidebar: 1fr;
		--dl-track-form2: 1fr 1fr;
		--dl-track-form3: 2fr 1fr 1fr;
		--dl-track-usp: repeat(2, 1fr);
		--dl-track-footer: 1fr 1fr;
		--dl-track-blog: repeat(2, 1fr);
		--dl-track-blog-rail: 1fr;
		--dl-track-wish: 80px 1fr 120px 140px auto;
		--dl-track-acct: 1fr;
		--dl-track-orders: 1.2fr 1fr 1fr 1fr auto;
		--dl-track-stats: repeat(3, 1fr);

		/* The carousels become grids: the row stops scrolling, the cards stop
		   being 200px wide and the bleed into the gutter goes. */
		--dl-row-display: grid;
		--dl-row-columns: var(--dl-track-g4);
		--dl-row-overflow: visible;
		--dl-row-snap: none;
		--dl-row-item: 0 1 auto;
		--dl-row-bleed: 0px;
		--dl-row-pad-block-end: 0px;

		/* The section header takes its full form from tablet up. */
		--dl-section-head-gap: var(--space-6); /* 20px */
		--dl-section-head-space: var(--space-7); /* 24px */
		--dl-section-head-eyebrow-gap: 6px; /* no token — optical */
		--dl-section-head-title-font: var(--type-h2);

		/*
		 * The hero becomes the two-column one: the finder card stops overlapping
		 * the edge and sits inside the wash, and the buttons stop being
		 * full-width — they sit side by side, sized by their labels.
		 */
		--dl-hero-pad-block-start: var(--space-10); /* 48px */
		--dl-hero-pad-block-end: var(--space-9); /* 40px */
		--dl-hero-gap: var(--space-8); /* 32px */
		--dl-hero-text-gap: var(--space-6); /* 20px */
		--dl-hero-title-font: var(--type-display);
		--dl-hero-title-max: 520px; /* no token — the headline measure as drawn */
		--dl-hero-lead-size: var(--text-lg);
		--dl-hero-lead-max: 480px; /* no token — the lead measure as drawn */
		--dl-hero-action-width: auto;
		--dl-hero-media-radius: var(--radius-2xl);
		--dl-hero-media-shadow: var(--shadow-2);
		--dl-hero-finder-gap: var(--space-9); /* 40px */
		--dl-hero-finder-pull: 0px;
		--dl-hero-band-pad-finder: var(--space-9); /* 40px — the card sits inside the wash */
		--dl-hero-overhang: 0px;

		/* The picker's three controls come onto one row. */
		--dl-vehicle-pad: var(--space-6); /* 20px */
		--dl-vehicle-cols: 1fr 1fr auto;

		--dl-promo-pad: var(--space-6); /* 20px */

		/* The teaser card stands up: plate on top, excerpt and "Les mer" back. */
		--dl-post-card-direction: column;
		--dl-post-card-plate-width: auto;
		--dl-post-card-plate-ratio: 16 / 9;
		--dl-post-card-pad: var(--space-6); /* 20px */
		--dl-post-card-title-font: var(--weight-regular) var(--text-lg) / 1.3 var(--font-display);
		--dl-post-card-excerpt-display: -webkit-box; /* the clamp needs the box */
		--dl-post-card-more-display: inline-flex;

		/* Still one column, but the air between the article and the rail opens up. */
		--dl-article-gap: var(--space-9); /* 40px */

		/* Header `compact`: still no MainNav and no account button, but the
		   search sits on the bar rather than under it. */
		--dl-header-pad-block: var(--space-5); /* 16px */
		--dl-header-gap: var(--space-5); /* 16px */
		--dl-header-row-gap: 0px;
		--dl-header-logo-w: 136px;
		--dl-header-actions-margin-end: calc(var(--space-1) - var(--dl-header-gap)); /* -12px */
		/* Basis 0, not `auto`: a flex line is broken on the item's *hypothetical*
		   size, before any shrinking, so a search whose basis is its content —
		   clamped to the 560px max — measures wider than the room left beside
		   the logo and the icons around 840px and drops the icons to a second
		   row. From a zero basis it simply grows into whatever is left, up to
		   the same 560px. */
		--dl-header-search-flex: 1 1 0;
		--dl-header-search-order: 0; /* source order — back on the bar */
		--dl-header-search-max: 560px;
		--dl-header-search-pad-end: var(--space-2);
		--dl-header-search-submit: inline-flex;
		--dl-fibo-input-pad-end: 96px; /* no token — the «Søk» button plus its 4px inset */

		/* One row taller than nothing and one shorter than mobile: the search is
		   back on the bar, so the header is topbar 36 + 16 + 44 + 16. */
		--dl-header-h: 115px;

		/* The catalogue keeps the drawer, but the bar has room for a sort control
		   sized by the design rather than by what is left of the row. */
		--dl-catalog-bar-pad: var(--space-4) var(--ds-gutter);
		--dl-catalog-sort-flex: 0 0 auto;
		--dl-catalog-sort-width: 200px;

		/* The matching categories are tiles from here up: a g4 grid, no scroll,
		   the plate back and the label under it where the design draws them. */
		--dl-search-count-space: 8px; /* no token — optical, under a 40px title */
		--dl-search-alert-space: var(--space-7); /* 24px */
		--dl-search-cats-space: var(--space-8); /* 32px */
		--dl-search-cat-cols: var(--dl-track-g4);
		--dl-search-cat-flow: row;
		--dl-search-cat-auto: auto;
		--dl-search-cat-overflow: visible;
		--dl-search-cat-bleed: 0px;
		--dl-search-cat-plate: grid;
		--dl-search-cat-meta-display: flex;
		--dl-search-cat-radius: var(--radius-lg);
		--dl-search-cat-foot-pad: var(--space-4) var(--space-5);
		--dl-search-cat-label-font: var(--weight-regular) var(--text-base) / var(--leading-snug) var(--font-display);
		--dl-search-cat-label-wrap: normal;
		--dl-search-sort-width: 210px; /* the width the handoff draws on this screen */

		/* The strip and the footer take their full form from tablet up: the grid
		   widens (usp 2-up, footer 2-up) and every piece mobile dropped is back. */
		--dl-usp-pad-block: var(--space-6); /* 20px — the band's own padding */
		--dl-usp-gap: var(--space-8); /* 32px */
		--dl-usp-item-gap: var(--space-4); /* 12px */
		--dl-usp-pill-size: 40px; /* no token — the pill diameter as drawn */
		--dl-usp-glyph-size: 18px;
		--dl-usp-title-font: var(--type-body-strong);
		--dl-usp-text-font: var(--type-small);

		--dl-footer-pad-block-start: var(--space-11); /* 64px */
		--dl-footer-gap: var(--space-9); /* 40px */
		--dl-footer-logo-w: 160px;
		--dl-footer-brand-display: flex;
		--dl-footer-blurb-display: block;
		--dl-footer-heading-display: block;
		--dl-footer-categories-display: block;
		--dl-footer-mail-icon-display: none;
		--dl-footer-copy-full-display: inline;
		--dl-footer-copy-short-display: none;
		--dl-footer-order-logo: 0;
		--dl-footer-order-information: 0;
		--dl-footer-order-contact: 0;
		--dl-footer-order-pay: 0;

		/* From tablet up the drawer is reached from the header hamburger and the
		   bottom bar goes. Zeroing the height rather than only hiding the bar is
		   what removes the padding it reserved. */
		--dl-bottom-nav-display: none;
		--dl-bottom-nav-h: 0px;

		/* Both bar spaces are 0 here, so this resolves to the plugin's own 20px
		   and the bubble sits exactly where it always did. */
		--dl-chat-inset: 20px;

		/*
		 * The product page keeps its single column here — bp.js gives tablet
		 * `product: 1fr` — but the gallery stops running to the screen edge and
		 * becomes the carded plate. A 794px square photograph is not a product
		 * shot, it is a wall, so the frame is capped and centred instead.
		 */
		--dl-product-gap: var(--space-8); /* 32px */
		--dl-product-title-font: var(--type-h2);
		--dl-gallery-max: 520px; /* no token — the plate's measure when it is alone in the column */
		--dl-gallery-bleed: 0px;
		--dl-gallery-frame-bg: var(--surface-card);
		--dl-gallery-frame-border: var(--border-width) solid var(--border-subtle);
		--dl-gallery-frame-radius: var(--radius-xl);
		--dl-gallery-inset: 16px;

		/* The review form wraps: name and e-mail take half the row each, less
		   half the form's 16px gap; everything else still spans it. */
		--dl-review-form-flow: row wrap;
		--dl-review-form-half: calc(50% - var(--space-3));

		/* The toast leaves the bottom edge and becomes a card in the corner. The
		   BottomNav is gone here, so the distance is the gutter plus whatever
		   the StickyBuyBar still takes on a product page. */
		--dl-toast-left: auto;
		--dl-toast-right: var(--ds-gutter);
		--dl-toast-w: 340px; /* no token — the handoff's toast measure */
		--dl-toast-gap: var(--ds-gutter);

		/*
		 * The cart line takes its wide shape here, one breakpoint before the rail
		 * does: 768px has room for the quantity and the line total beside the
		 * title, and the tighter variant exists for 390px, not for 834.
		 */
		--dl-cart-gap: var(--space-6); /* 20px */
		--dl-cart-card-pad-inline: var(--space-6); /* 20px */
		--dl-cart-actions-pad: var(--space-6) 0;
		--dl-cart-actions-wrap: nowrap;

		/* The two form grids open up at 768, one breakpoint before the rail. */
		--dl-checkout-field-gap: var(--space-5); /* 16px */

		/* Postnummer takes a fixed short column; Poststed and the street share
		   the rest. Below this the postcode and the town are a pair. */
		--dl-track-address: 160px 1fr 1fr; /* no token — the postcode column */
		--dl-checkout-tiles-ship: 1fr 1fr;

		--dl-cartline-plate: 84px; /* no token — the full CartLine thumbnail */
		--dl-cartline-cols: var(--dl-cartline-plate) 1fr auto minmax(110px, auto) auto;
		--dl-cartline-areas: 'plate info qty price remove';
		--dl-cartline-align: center;
		--dl-cartline-gap: var(--space-5); /* 16px */
		--dl-cartline-price-align: end;
		--dl-cartline-price-width: 110px; /* no token — the CartLine's price column */
		--dl-cartline-unit-display: flex;
	}
}

@media (min-width: 1024px) {
	:root {
		--ds-grid-gutter: var(--grid-gutter); /* 20px */
		--ds-section-rhythm: var(--space-11); /* 64px */

		/* bp.js desktop defaults `D` — md and lg share them verbatim. */
		--dl-track-g4: repeat(4, 1fr);
		--dl-track-g3: repeat(3, 1fr);
		--dl-track-cards: repeat(3, 1fr);
		--dl-track-hero: 1.1fr 1fr;
		--dl-track-product: 1.15fr 1fr;
		--dl-track-rail: 1fr 380px;
		--dl-track-sidebar: 280px 1fr;
		--dl-track-form2: 1fr 1fr;
		--dl-track-form3: 2fr 1fr 1fr;
		--dl-track-usp: repeat(4, 1fr);
		--dl-track-footer: 1.4fr 1fr 1fr 1fr;
		--dl-track-blog: repeat(3, 1fr);
		--dl-track-blog-rail: 1fr 320px;
		--dl-track-wish: 92px 1fr 150px 170px auto;
		--dl-track-acct: 260px 1fr;
		--dl-track-orders: 1.2fr 1fr 1fr 1fr auto;
		--dl-track-stats: repeat(3, 1fr);

		/* Running copy: the list markers hang outside the column from here up. */
		--dl-prose-list-indent: 0px;

		/*
		 * The article gets its rail — bp.js `blogRail` is `1fr 320px` from here —
		 * and the rail sticks. The offset is measured rather than drawn: the
		 * handoff's `top: 160` was a snapshot of one screen's header height, and
		 * assets/js/sticky.js writes the real one into --dl-header-h. #14's rule,
		 * the same as --dl-summary-top below.
		 *
		 * The table of contents comes back here, which is where there is a column
		 * beside the copy to put it in.
		 */
		--dl-article-gap: var(--space-10); /* 48px */
		--dl-article-rail-position: sticky;
		--dl-article-rail-top: calc(var(--ds-sticky-offset) + var(--dl-header-h) + var(--space-6));
		--dl-article-toc-display: block;

		/* The hero opens up: 80px of air above it and 48px between its columns. */
		--dl-hero-pad-block-start: var(--space-12); /* 80px */
		--dl-hero-gap: var(--space-10); /* 48px */

		/* Header `full`: the department bar appears, the hamburger goes, the
		   account button and the full topbar come back. Pointer is a mouse from
		   here up, so the actions drop to the 40px control height. */
		--dl-header-gap: var(--space-8); /* 32px */
		--dl-header-action-size: var(--control-h-md); /* 40px */
		--dl-header-logo-w: 168px;
		--dl-header-menu-display: none;
		--dl-header-actions-margin-end: 0px; /* no hamburger to close the gap to */
		--dl-header-account-display: inline-flex;
		--dl-topbar-full-display: inline-flex;
		--dl-mainnav-display: block;
		--dl-promo-label-display: block;
		--dl-promo-gap: var(--space-5); /* 16px */
		--dl-promo-pad-block: var(--space-4); /* 12px — the band height in the handoff */

		/* topbar 36 + 16 + 40 + 16 + the department bar 44. */
		--dl-header-h: 152px;

		/*
		 * The catalogue takes its desktop shape: the 280px sidebar is back, the
		 * filter button and the sticky bar go with the drawer, and the head's
		 * three cells — count, chips, sort — sit on one line. The bar itself
		 * becomes `display: contents` so its children are those cells; see
		 * section 3 of screens.css.
		 */
		--dl-catalog-gap: var(--space-9); /* 40px between the sidebar and the grid */
		--dl-catalog-sidebar-display: flex;
		--dl-catalog-header-space: var(--space-7); /* 24px */
		--dl-catalog-title-font: var(--type-h1);
		--dl-catalog-head-display: grid;
		--dl-catalog-head-cols: auto 1fr auto;
		--dl-catalog-head-gap: var(--space-4); /* 12px between the cells */
		--dl-catalog-head-space: var(--space-6); /* 20px above the grid */
		--dl-catalog-bar-space: 0px;
		--dl-catalog-tags-space: 0px;
		--dl-catalog-bar-display: contents;
		--dl-catalog-bar-position: static;
		--dl-catalog-bar-pad: 0;
		--dl-catalog-bar-bleed: 0px;
		--dl-catalog-bar-border: 0;
		--dl-catalog-bar-bg: transparent;
		--dl-catalog-filter-btn-display: none;
		--dl-catalog-pagination-space: var(--space-9); /* 40px */

		/* Count · chips · sort, left to right, whatever the source order is. */
		--dl-catalog-count-col: 1;
		--dl-catalog-tags-col: 2;
		--dl-catalog-sort-col: 3;

		/* The row is stated as well as the column: grid auto-placement is sparse,
		   so the chips — which come after the sort in the source — would be sent
		   to a second row rather than back to the cell between them. */
		--dl-catalog-head-row: 1;

		/*
		 * The product screen takes its two-column shape: the gallery gains the
		 * thumbnail rail and loses the dot pager, the wishlist heart moves off the
		 * plate and into the cart row, the panels become tabs, and the sticky buy
		 * bar goes along with the bottom bar — the buy box is on screen.
		 */
		--dl-product-gap: var(--space-10); /* 48px between the two columns */
		--dl-product-head-space: var(--space-6); /* 20px */
		--dl-product-title-font: var(--type-h2);
		--dl-buybox-gap: var(--space-5); /* 16px */
		--dl-buybox-wishlist-display: inline-flex;

		--dl-gallery-display: flex;
		--dl-gallery-gap: var(--space-4); /* 12px between the rail and the plate */
		--dl-gallery-max: none;
		/*
		 * 480px is the tallest plate that still leaves the price, the stock line
		 * and the cart row beside it on a 1024x768 screen under the header. The
		 * plate keeps the full width of the column and stops at this height; the
		 * square it reserves below the cap is the same square as before. The rail
		 * is capped to whatever the plate actually came out at — this, or what the
		 * column leaves once the chips and the gap are off it, whichever is less.
		 */
		--dl-gallery-plate-max: 480px;
		--dl-gallery-rail-max: min(
			var(--dl-gallery-plate-max),
			calc(100cqi - var(--dl-gallery-thumb-size) - var(--dl-gallery-gap))
		);
		--dl-gallery-container: inline-size;
		--dl-gallery-rail-display: flex;
		--dl-gallery-dots-display: none;
		--dl-gallery-wishlist-display: none;

		--dl-prodinfo-space: var(--space-11); /* 64px */
		--dl-prodinfo-display: block;
		--dl-prodinfo-list-display: flex;
		/*
		 * The card is kept at every width. The handoff draws the desktop strip flat
		 * on the page, and flat is what the first build did — but the block carries
		 * --surface-card against a --surface-page background, so what it actually
		 * drew was a white panel with its text against the edge on three sides. A
		 * surface with no padding is not a flat treatment, it is a broken card. It
		 * is the same object as the accordion below 1024px; only the header row's
		 * direction changes.
		 */
		--dl-prodinfo-border: var(--border-width) solid var(--border-subtle);
		--dl-prodinfo-radius: var(--radius-lg);
		/* The focus ring on a tab is drawn outside the tab's box, and the card must
		   not clip it — the accordion's rows have no ring to lose. */
		--dl-prodinfo-overflow: visible;
		/*
		 * The measure is imposed on the whole block rather than on the panel body:
		 * with the strip's rule spanning the 1320px container and the text stopping
		 * at 760, the panel read as a narrow column parked under an unrelated
		 * hairline. 810 is the measure plus the card's own padding and its two
		 * hairlines, so the text column inside is exactly the 760 the design draws.
		 */
		--dl-prodinfo-max: 810px; /* no token — 760 measure + 2×24 padding + 2 hairlines */
		/* Inline padding is the card's; the block padding is the hit area, and the
		   14px keeps the indicator on the rule the strip sits above. */
		--dl-prodinfo-tab-pad: var(--space-5) var(--space-7) 14px; /* no token — see above */
		/*
		 * The strip reads as controls rather than as a sentence through weight,
		 * colour and hit area: --weight-medium in the display face against the
		 * panel's --weight-light body, --text-muted lifting to --text-heading on the
		 * selected tab (3.9:1 between the two, above the 3:1 the AC asks for) and on
		 * hover, and the padding block above. The weight is the same in every state
		 * on purpose — making the selected tab bolder re-sizes it inside a flex row
		 * and shifts every tab after it. State is carried by colour and by the 2px
		 * --brand indicator, neither of which changes a box.
		 */
		--dl-prodinfo-tab-font: var(--weight-medium) var(--text-base) / 1.35 var(--font-display);
		/*
		 * No gap: the 24px each tab carries on both sides already sets the labels
		 * 48px apart, and the padding is what has to align — the first label sits on
		 * the same line as the panel's text below it. A gap on top of that would
		 * push the strip's rhythm off the card's.
		 */
		--dl-prodinfo-tab-gap: 0px;
		--dl-prodinfo-tab-hover-bg: var(--surface-page);
		/* The two swap: the rows lose their separator, the strip gains the rule
		   the selected tab's 2px indicator is painted onto. */
		--dl-prodinfo-row-rule: 0;
		--dl-prodinfo-list-rule: var(--border-width) solid var(--border-subtle);
		--dl-prodinfo-chevron-display: none;
		--dl-prodinfo-panel-pad: var(--space-7);
		--dl-prodinfo-panel-max: 760px; /* no token — the reading measure as drawn */
		--dl-prodinfo-spec-label-width: 220px; /* no token — the label column as drawn */
		/* 30 rows scanned for one value need the label column to look like one:
		   weight separates the two cells where colour alone did not. */
		--dl-spec-label-weight: var(--weight-medium);

		--dl-buybar-display: none;
		--dl-buybar-h: 0px;

		/* The one width the mini-cart exists at. Below it the header's cart
		   button is the link it looks like. */
		--dl-minicart-display: flex;

		/*
		 * The cart's rail appears here — bp.js `rail: side` from md up — and the
		 * summary sticks. The offset is measured, not drawn: assets/js/sticky.js
		 * writes the header's real height into --dl-header-h, which is what the
		 * handoff's `top: 160` was a snapshot of on one screen. #14's rule.
		 */
		--dl-cart-gap: var(--space-9); /* 40px between the lines and the rail */
		--dl-cart-steps-space: var(--space-7); /* 24px */
		--dl-cart-title-space: var(--space-8); /* 32px */
		--dl-cart-title-font: var(--type-h1);
		--dl-cart-card-pad-inline: var(--space-7); /* 24px */
		--dl-summary-position: sticky;
		--dl-summary-top: calc(var(--ds-sticky-offset) + var(--dl-header-h) + var(--space-6));

		--dl-checkout-block-pad: var(--space-7); /* 24px */
		--dl-checkout-block-gap: var(--space-5); /* 16px */
		--dl-checkout-block-head-gap: var(--space-6); /* 20px */
		--dl-checkout-step-size: 26px; /* no token — the pill as drawn */
		--dl-checkout-block-title-font: var(--type-h3);
		--dl-checkout-done-pad: var(--space-9) 0;

		--dl-checkout-section-gap: var(--space-8); /* 32px */
		--dl-checkout-head-gap: var(--space-5); /* 16px */
		--dl-checkout-rail-pad: var(--space-7); /* 24px */
		--dl-checkout-title-font: var(--type-h1);
		--dl-checkout-tiles-pay: repeat(3, 1fr);

		/* Min konto: the sidebar becomes a card again and the orders stop
		   applying — the identity and the menu are back inside it. */
		--dl-acct-side-display: block;
		--dl-acct-side-position: sticky;
		--dl-acct-side-top: calc(var(--ds-sticky-offset) + var(--dl-header-h) + var(--space-6));
		--dl-acct-gap: var(--space-9); /* 40px between the sidebar and the screen */
		--dl-acct-id-order: 0;
		--dl-acct-main-order: 0;
		--dl-acct-menu-order: 0;
		--dl-acct-id-pad: var(--space-4);
		--dl-acct-id-gap: var(--space-4);
		--dl-acct-avatar-size: 40px; /* no token — AccountScreen's monogram */
		--dl-acct-avatar-font: var(--weight-medium) var(--text-base) / 1 var(--font-display);
		--dl-acct-name-font: var(--type-body-strong);

		--dl-acct-menu-gap: 0px;
		--dl-acct-menu-row-bg: transparent;
		--dl-acct-menu-row-pad: 10px var(--space-4); /* 10px — as drawn */
		--dl-acct-menu-row-radius: var(--radius-sm);
		--dl-acct-menu-chevron: none;
		--dl-acct-menu-rule-display: block;

		--dl-acct-stat-pad: var(--space-6);
		--dl-acct-stat-direction: row;
		--dl-acct-stat-align: center;
		--dl-acct-stat-gap: var(--space-4);
		--dl-acct-stat-icon-size: 38px; /* no token — the pill as drawn */
		--dl-acct-stat-icon-bg: var(--brand-subtle);
		--dl-acct-stat-icon-color: var(--brand);
		--dl-acct-stat-value-font: var(--type-h3);

		--dl-order-head-display: grid;
		--dl-order-row-gap: var(--space-5);
		--dl-order-id-area: auto;
		--dl-order-date-area: auto;
		--dl-order-status-area: auto;
		--dl-order-total-area: auto;
		--dl-order-action-area: auto;
		--dl-order-cell-justify: start;
		--dl-order-cell-align: start;
		--dl-order-action-justify: end;
		--dl-order-action-width: auto;
	}
}

@media (min-width: 1440px) {
	:root {
		/* lg differs from md only in vertical rhythm; the grid tracks are the same. */
		--ds-section-rhythm: var(--space-12); /* 80px */
	}
}

/*
 * The one query here that is not a breakpoint: a capability, not a width.
 *
 * The design reveals the wishlist heart on hover. On a touch screen there is no
 * hover to reveal it with, so the control would be undiscoverable — it is shown
 * at rest instead. Same markup, one property.
 */
:root {
	--dl-hover-reveal: 1;
}

@media (hover: hover) and (pointer: fine) {
	:root {
		--dl-hover-reveal: 0;

		/*
		 * The gallery's hover zoom, for the same reason: it is a pointer that
		 * reveals it, not a width. A touch screen would be left with an image
		 * that scales on tap and never scales back.
		 */
		--dl-gallery-zoom: 1.03; /* no token — the zoom as drawn */
	}
}

/* ══ 2. Element defaults ═════════════════════════════════════════════════════
 *
 * Type is set through the composite roles (--type-h1, --type-body …), never
 * through their parts. The block editor applies its own reset to the canvas; we
 * stay off `.editor-styles-wrapper` internals and only style plain elements, so
 * the two do not fight.
 */

h1 {
	font: var(--type-h1);
	letter-spacing: var(--tracking-tight);
}

h2 {
	font: var(--type-h2);
	letter-spacing: var(--tracking-snug);
}

h3 {
	font: var(--type-h3);
}

/* The role scale stops at h4; h5 and h6 share it rather than inventing a size. */
h4,
h5,
h6 {
	font: var(--type-h4);
}

/*
 * Links: --text-brand is --blue-700 and tokens/base.css already sets the hover to
 * --blue-800 with the control transition. Underlines are on for links inside
 * running copy only — chrome, cards and navigation carry their own affordance.
 */
.dl-prose a:not([class]),
.entry-content a:not([class]) {
	text-decoration: underline;
	text-underline-offset: 2px;
	text-decoration-thickness: 1px;
	text-decoration-color: var(--blue-200);
}

.dl-prose a:not([class]):hover,
.entry-content a:not([class]):hover {
	text-decoration-color: currentColor;
}

ul,
ol {
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * Running copy keeps real list markers; chrome lists do not. The indent is a
 * breakpoint variable, not a constant: see --dl-prose-list-indent in section 1
 * for why it goes to zero on desktop.
 */
.dl-prose ul,
.dl-prose ol,
.entry-content ul,
.entry-content ol {
	margin: 0 0 var(--space-5);
	padding-inline-start: var(--dl-prose-list-indent);
	list-style: revert;
}

/*
 * A nested list is indented at every width. It is the one place the markers
 * cannot hang: outside its own column is where its parent's text is, and the
 * two levels would read as one.
 */
.dl-prose li > ul,
.dl-prose li > ol,
.entry-content li > ul,
.entry-content li > ol {
	margin-block-end: 0;
	padding-inline-start: var(--space-6);
}

.dl-prose > * + *,
.entry-content > * + * {
	margin-top: var(--space-5);
}

hr {
	height: var(--border-width);
	margin: var(--space-8) 0;
	border: 0;
	background: var(--border-subtle);
}

table {
	width: 100%;
	border-collapse: collapse;
	font: var(--type-small);
	color: var(--text-body);
}

caption {
	font: var(--type-caption);
	color: var(--text-muted);
	text-align: left;
	padding-bottom: var(--space-3);
}

th {
	font: var(--type-body-strong);
	color: var(--text-heading);
	text-align: left;
}

th,
td {
	padding: var(--space-4) var(--space-5);
	border-bottom: var(--border-width) solid var(--border-subtle);
	vertical-align: top;
}

tbody tr:last-child > * {
	border-bottom: 0;
}

/* Form controls inherit the body face — browsers otherwise fall back to their own. */
button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
	letter-spacing: inherit;
}

button {
	margin: 0;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
}

textarea {
	resize: vertical;
}

fieldset {
	margin: 0;
	padding: 0;
	border: 0;
	min-inline-size: 0;
}

legend {
	padding: 0;
	font: var(--type-body-strong);
	color: var(--text-heading);
}

::placeholder {
	color: var(--text-faint);
	opacity: 1;
}

code,
kbd,
samp,
pre {
	font: var(--type-mono);
	color: var(--text-body);
}

/* SKU, part and fitment codes — mono, faint, wide tracking. */
.dl-code {
	font: var(--type-mono);
	color: var(--text-faint);
	letter-spacing: var(--tracking-wide);
}

/* The 11px uppercase eyebrow above section headings. */
.dl-eyebrow {
	display: block;
	font: var(--type-eyebrow);
	letter-spacing: var(--tracking-caps);
	text-transform: uppercase;
	color: var(--text-brand);
}

/* ══ 3. Layout utilities ═════════════════════════════════════════════════════ */

/*
 * Content column: capped at --container-max with the per-breakpoint side gutter.
 * Below 1320px the cap is inert and the container is the full viewport, which is
 * what bp.js expresses as container: '100%' on mobile and tablet.
 */
.dl-container {
	width: 100%;
	max-width: var(--container-max);
	margin-inline: auto;
	padding-inline: var(--ds-gutter);
}

/* Full-bleed band whose inner content still respects the container. */
.dl-container--bleed {
	max-width: none;
	padding-inline: 0;
}

/* Vertical rhythm between page sections. */
.dl-section {
	padding-block: var(--dl-section-pad, var(--ds-section-rhythm));
}

/*
 * The screens that open a document at the top of the page take the tighter
 * 16px instead of the rhythm — the head sits under the header, not a row
 * below the one before it. Both classes are on the .dl-section itself.
 */
.dl-section.dl-shop,
.dl-section.dl-blog {
	--dl-section-pad: var(--space-5); /* 16px */
}

.dl-section--flush-top {
	padding-block-start: 0;
}

.dl-section--flush-bottom {
	padding-block-end: 0;
}

/* Rhythm as a gap, for a column of sections that must not double up on padding. */
.dl-sections {
	display: flex;
	flex-direction: column;
	gap: var(--ds-section-rhythm);
}

/*
 * Grid tracks. One class per `g:` key in bp.js; the values themselves live in the
 * breakpoint block above, so a screen never restates them.
 */
.dl-grid {
	display: grid;
	gap: var(--ds-grid-gutter);
}

.dl-grid--g4 { grid-template-columns: var(--dl-track-g4); }
.dl-grid--g3 { grid-template-columns: var(--dl-track-g3); }
.dl-grid--cards { grid-template-columns: var(--dl-track-cards); }
.dl-grid--hero { grid-template-columns: var(--dl-track-hero); }
.dl-grid--product { grid-template-columns: var(--dl-track-product); }
.dl-grid--rail { grid-template-columns: var(--dl-track-rail); }
.dl-grid--sidebar { grid-template-columns: var(--dl-track-sidebar); }
.dl-grid--form2 { grid-template-columns: var(--dl-track-form2); }
.dl-grid--form3 { grid-template-columns: var(--dl-track-form3); }
.dl-grid--usp { grid-template-columns: var(--dl-track-usp); }
.dl-grid--footer { grid-template-columns: var(--dl-track-footer); }
.dl-grid--blog { grid-template-columns: var(--dl-track-blog); }
.dl-grid--blog-rail { grid-template-columns: var(--dl-track-blog-rail); }
.dl-grid--wish { grid-template-columns: var(--dl-track-wish); }
.dl-grid--acct { grid-template-columns: var(--dl-track-acct); }
.dl-grid--orders { grid-template-columns: var(--dl-track-orders); }
.dl-grid--stats { grid-template-columns: var(--dl-track-stats); }

/* ══ 4. Focus ════════════════════════════════════════════════════════════════
 *
 * The one focus rule in the theme. tokens/base.css sets the ring; this adds the
 * brand border the design system pairs with it. No component may override or
 * remove any of it — see the "Focus" section of the design system guide.
 *
 * Three halves, not two. `border-color` draws nothing on an element whose
 * `border-style` is `none` — every <a> in the theme, and the button variants
 * that carry no border — and the halo alone is 1.34:1 on white and 1.28:1 on
 * the --neutral-900 footer, half of the 3:1 SC 1.4.11 asks of an indicator. So
 * the same --border-brand hairline is drawn as an outline as well, at a
 * negative offset: on a control that already has a border the outline lands on
 * top of it and the control looks exactly as the design draws it; on a link it
 * is the whole indicator. The halo is unchanged and stays what it always was —
 * decoration around the line that does the work.
 */
:focus-visible {
	outline: var(--dl-focus-outline, var(--border-width) solid var(--border-brand));
	outline-offset: calc(var(--border-width) * -1);
	border-color: var(--border-brand);
	box-shadow: var(--focus-ring);
}

/* ══ 5. WordPress glue ═══════════════════════════════════════════════════════ */

/*
 * Global styles turn the root blockGap into a top margin on every top-level
 * block — `:where(.wp-site-blocks) > * { margin-block-start: … }`. The theme
 * carries its page rhythm on the sections themselves (see .dl-section above),
 * so that margin only ever double-spaces the top of a page. The class selector
 * outranks the `:where()` regardless of stylesheet order.
 */
.wp-site-blocks > * {
	margin-block-start: 0;
}

/*
 * Skip link — visually hidden until focused, and the theme's own: core's
 * JS-injected one is unhooked in inc/setup.php, because the one control whose
 * whole job is to work before anything else does should not need JavaScript.
 *
 * The compound selector is deliberate. Core prints `.skip-link.screen-reader-text`
 * as an inline style and a plain `.skip-link` rule loses to it, which is what
 * used to paint the chip core's grey rather than the design's card. Matching the
 * specificity means the theme wins whether or not that style is on the page —
 * and the `position` in the focus rule is what beats `.screen-reader-text:focus`,
 * which reveals the link and would otherwise leave it in the flow.
 */
.skip-link,
.skip-link.screen-reader-text {
	position: absolute;
	left: -9999px;
	z-index: 999;
	padding: var(--space-3) var(--space-5);
	background: var(--surface-card);
	color: var(--text-brand);
	border-radius: var(--radius-sm);
	box-shadow: var(--shadow-3);
}

.skip-link:focus,
.skip-link.screen-reader-text:focus {
	position: absolute;
	left: var(--space-5);
	top: var(--space-5);
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.screen-reader-text:focus {
	position: static;
	width: auto;
	height: auto;
	margin: 0;
	overflow: visible;
	clip-path: none;
	white-space: normal;
}

/* Hidden until a script reveals it — drawers, dialogs, toast regions. */
[hidden] {
	display: none !important;
}

/*
 * The admin bar offsets the viewport; keep sticky chrome below it. Everything
 * that sticks reads --ds-sticky-offset as its `top`, never a literal 0.
 *
 * Declared on :root rather than on <body>, because the scroll-padding below
 * reads it and the scrollport is the root element — a custom property set on
 * the body is not visible to it. `admin-bar` is a body class, so :has() is what
 * carries it up one level; everything downstream inherits exactly as before.
 */
:root {
	--ds-sticky-offset: 0px;
}

:root:has(body.admin-bar) {
	--ds-sticky-offset: 32px;
}

/* 782px is WordPress's own admin-bar breakpoint, not a design breakpoint — it is
   the one query in the theme that does not come from the table in section 1. */
@media (max-width: 782px) {
	:root:has(body.admin-bar) {
		--ds-sticky-offset: 46px;
	}
}

/* Core drops the bar out of fixed positioning at 600px, so there is nothing
   left to clear. 600 and 782 are both WordPress's numbers, not the design's. */
@media (max-width: 600px) {
	:root:has(body.admin-bar) {
		--ds-sticky-offset: 0px;
	}
}

/*
 * SC 2.4.11 Focus Not Obscured. Tab to an element the browser has to scroll
 * into view and it stops the moment the element is inside the scrollport —
 * which, with a sticky header and two fixed bars, is under them. scroll-padding
 * on the scrollport tells it where the visible part actually starts and ends,
 * once, for every jump in the theme: the sticky offset plus the measured header
 * at the top, the bottom bar plus the buy bar at the foot. All four collapse to
 * 0 where the chrome they name is not on screen.
 *
 * This is the theme's answer to the whole question. A component must not add a
 * scroll-margin of its own on top of it.
 */
html {
	scroll-padding-block-start: calc(var(--ds-sticky-offset) + var(--dl-header-h) + var(--space-6));
	scroll-padding-block-end: calc(var(--dl-bottom-nav-space) + var(--dl-buybar-space));
}
