/* sottopizza.nl
   Loaded after the Bootstrap 5.3 stylesheet, so anything below wins.
   Single mobile breakpoint: 768px. Nothing on this site switches at any
   other width.

   The palette and the type are derived from the old SOTTO Pizza site in
   input/, not from taste: near-black over pure white, achromatic,
   condensed uppercase headings, hard corners, rules as the only
   ornament. The one departure is a single accent colour, which the
   restaurant site did not need and a guide with links, an FAQ accordion
   and affiliate CTAs does. Reasoning in plan/SOTTOPIZZA-build-notes.md
   under "build-design - rework". */

:root {
  --surface: #FFFFFF;
  --surface-alt: #F4F4F4;
  --ink: #141414;
  --muted: #5E5E5E;
  --brand: #0F5C34;
  --brand-deep: #0A4527;
  --accent: #0F5C34;
  --accent-light: #79D6A6;
  --rule: #D8D8D8;
  --rule-soft: #E7E7E7;

  /* Affiliate CTA only. Used for nothing else on the site, which is the
     whole point: the accent already carries links, headings, badges and
     rules, so a CTA painted in it reads as more of the same. Derived
     rather than imported — it is the triadic partner of the accent
     (H148.8 - 120 = H28.8) at full saturation, so it still belongs here.
     White on it is 5.85:1, hover is 8.31:1, and the hover darkens the same
     hue instead of moving to another one. Not the old rust: that was
     H14.6 and it was the page ground, this is one button. */
  --cta: #A34C00;
  --cta-deep: #7F3B00;

  /* Star rating only, and its own pair rather than borrowed tokens: the
     track used to be --rule, so a border tweak would have silently
     changed how a 4.6 reads. Gold because a rating is gold nearly
     everywhere and a reader recognises it before reading it — never the
     accent, which is what made the stars vanish into the page here. Kept
     yellower and lighter than --cta (H45 L47 against H29 L32) so the two
     warm things in a card do not compete and the CTA still wins. The
     track is deliberately not lighter than #ddd: the partial star exists
     only as the contrast between these two, and a near-white track turns
     every rating into five full stars. */
  --star: #EFAE00;
  --star-track: #D6D6D6;

  --font-head: "Oswald", "Arial Narrow", Helvetica, sans-serif;
  --font-body: "IBM Plex Sans", Helvetica, Arial, sans-serif;

  /* Hard corners are the anchor's most consistent trait. */
  --radius: 0;
  --radius-pill: 0;
  --hero-radius: 0;

  --page: 1240px;
  --measure: 72ch;
  --bar: 60px;

  --gap-xs: .4rem;
  --gap-sm: .8rem;
  --gap: 1.6rem;
  --gap-lg: 3rem;
  --gap-xl: 5rem;

  --shadow: 0 1px 0 rgba(20, 20, 20, .06);
  --shadow-lift: 0 10px 30px rgba(20, 20, 20, .16);
}

/* Bootstrap token overrides. Doing it here rather than fighting the
   framework rule by rule further down. */
:root {
  --bs-body-bg: var(--surface);
  --bs-body-color: var(--ink);
  --bs-body-font-family: var(--font-body);
  --bs-body-font-size: 1.0625rem;
  --bs-body-line-height: 1.7;
  --bs-link-color: var(--accent);
  --bs-link-hover-color: var(--brand-deep);
  --bs-border-color: var(--rule);
  --bs-border-radius: var(--radius);
  --bs-emphasis-color: var(--ink);
  --bs-secondary-color: var(--muted);
}


/* ---------- base ---------- */

/* Bootstrap already sets this and loads first, so on a live page the value
   is unchanged. It is restated because the box model should not depend on
   a CDN stylesheet arriving: with Bootstrap blocked or slow, every sized
   element that also carries padding grows by that padding, and the
   affiliate product boxes overflow their column. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(1rem, .96rem + .18vw, 1.0625rem);
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-head);
  color: var(--ink);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: .01em;
  text-transform: uppercase;
  margin: 0 0 var(--gap-sm);
}

h1 { font-size: clamp(2rem, 1.55rem + 1.9vw, 2.9rem); }
h2 {
  font-size: clamp(1.55rem, 1.3rem + 1.05vw, 2.15rem);
  margin-top: var(--gap-lg);
  padding-bottom: .45rem;
  border-bottom: 1px solid var(--rule);
}
h3 { font-size: clamp(1.22rem, 1.12rem + .45vw, 1.45rem); margin-top: var(--gap); }
h4 { font-size: 1.1rem; margin-top: var(--gap); font-weight: 600; }

/* Anchor targets for the in-article table of contents; on mobile the
   fixed header would otherwise sit on top of the heading it jumped to. */
h2, h3, h4 { scroll-margin-top: 1.5rem; }

p { margin: 0 0 1.15em; }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  text-decoration-color: rgba(15, 92, 52, .45);
}

a:hover,
a:focus-visible { color: var(--brand-deep); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* The global ring is --accent, which is a DARK green: on the ink header
   band and the mobile nav panel it lands at roughly 1.3:1 and a keyboard
   user tabs through the nav blind. The light tint is already the active-nav
   colour on that band, so the ring joins an existing convention. */
.sto-header :focus-visible,
.sto-mobile-nav :focus-visible {
  outline-color: var(--accent-light);
}

img { max-width: 100%; height: auto; }

hr {
  border: 0;
  border-top: 1px solid var(--rule);
  opacity: 1;
  margin: var(--gap-lg) 0;
}

::selection { background: rgba(15, 92, 52, .18); }

/* ---------- header ---------- */

.sto-header {
  background: var(--ink);
  position: relative;
  z-index: 100;
}

.sto-header-inner {
  max-width: var(--page);
  margin-inline: auto;
  padding: 1.35rem 2rem 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .9rem;
}

.sto-header-top {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}

.sto-logo {
  grid-column: 2;
  justify-self: center;
  display: inline-flex;
  line-height: 0;
}

.sto-logo img {
  height: 44px;
  width: auto;
}

.sto-header-tools {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: .35rem;
}

.sto-nav { width: 100%; }

.sto-nav-list {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0 2.1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.sto-nav-list a {
  display: block;
  padding: .55rem 0 1rem;
  color: rgba(255, 255, 255, .82);
  font-family: var(--font-head);
  font-size: .95rem;
  font-weight: 400;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: color .18s ease, border-color .18s ease;
}

.sto-nav-list a:hover { color: #fff; }

.sto-nav-list a.active {
  color: #fff;
  border-bottom-color: var(--accent-light);
}

.sto-search-trigger,
.sto-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, .82);
  cursor: pointer;
  transition: color .18s ease;
}

.sto-search-trigger:hover,
.sto-menu-toggle:hover { color: #fff; }

.sto-menu-toggle { display: none; }

/* Hamburger, three bars via the element plus its two pseudo-elements. */
.sto-hamburger,
.sto-hamburger::before,
.sto-hamburger::after {
  display: block;
  width: 21px;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
  transition: transform .22s ease, opacity .18s ease;
}

.sto-hamburger { position: relative; }

.sto-hamburger::before,
.sto-hamburger::after {
  content: "";
  position: absolute;
  left: 0;
}

.sto-hamburger::before { top: -6px; }
.sto-hamburger::after { top: 6px; }

.sto-menu-toggle[aria-expanded="true"] .sto-hamburger { background: transparent; }
.sto-menu-toggle[aria-expanded="true"] .sto-hamburger::before { transform: translateY(6px) rotate(45deg); }
.sto-menu-toggle[aria-expanded="true"] .sto-hamburger::after { transform: translateY(-6px) rotate(-45deg); }

/* Default state is hidden; the mobile media query re-shows it only when
   the toggle has removed .hidden. Inverting with :not() keeps the
   desktop default intact and keeps the JS class and the CSS in
   agreement. */
.sto-mobile-nav { display: none; }

.sto-mobile-nav ul {
  list-style: none;
  margin: 0;
  padding: .4rem 0 1rem;
}

.sto-mobile-nav a {
  display: block;
  padding: .85rem 1.15rem;
  color: rgba(255, 255, 255, .86);
  font-family: var(--font-head);
  font-size: 1rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, .12);
}

.sto-mobile-nav a.active { color: var(--accent-light); }


/* ---------- search modal ---------- */

.sto-search-modal { position: fixed; inset: 0; z-index: 300; }
.sto-search-modal[hidden] { display: none; }

.sto-search-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 20, 20, .55);
}

.sto-search-panel {
  position: relative;
  max-width: 620px;
  margin: 9vh auto 0;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  padding: 1.4rem 1.4rem 1rem;
}

.sto-search-input {
  width: 100%;
  padding: .75rem 2.6rem .75rem .9rem;
  font-family: var(--font-body);
  font-size: 1.05rem;
  color: var(--ink);
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.sto-search-input::placeholder { color: var(--muted); }

.sto-search-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  background: var(--surface);
}

.sto-search-close {
  position: absolute;
  top: 1.55rem;
  right: 1.7rem;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.sto-search-close:hover { color: var(--brand); background: var(--surface-alt); }

.sto-search-results { margin-top: .9rem; max-height: 58vh; overflow-y: auto; }
.sto-search-results[hidden] { display: none; }

.sto-search-results a {
  display: block;
  padding: .7rem .55rem;
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

.sto-search-results a:last-child { border-bottom: 0; }
.sto-search-results a:hover,
.sto-search-results a:focus-visible { background: var(--surface-alt); }

.sto-search-results strong {
  display: block;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.02rem;
}

.sto-search-results small {
  display: block;
  margin-top: .1rem;
  color: var(--muted);
  font-size: .82rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.sto-search-empty {
  padding: 1.1rem .55rem;
  color: var(--muted);
  font-size: .95rem;
}

/* Appended under the last hit when more matches exist than the cap shows,
   so a broad query does not silently lose its tail. Deliberately quieter
   than a result row: it is a control, not an article. */
.sto-search-meer {
  display: block;
  width: 100%;
  margin-top: .3rem;
  padding: .7rem .55rem;
  border: 0;
  border-top: 1px solid var(--rule);
  background: none;
  color: var(--brand);
  font-family: var(--font-head);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}

.sto-search-meer:hover { color: var(--brand-deep); background: var(--surface-alt); }

body.sto-search-open { overflow: hidden; }


/* ---------- predecessor notice (variant 4) ---------- */
/* Untinted band on the page background, one hairline above and below.
   Container width and horizontal padding match the page container so the
   text starts on the same vertical line as the H1 underneath it. */

.sto-mededeling {
  background: var(--surface);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.sto-mededeling-inner {
  max-width: var(--page);
  margin-inline: auto;
  padding: .95rem 2rem;
}

.sto-mededeling p {
  margin: 0;
  max-width: 62ch;
  color: var(--muted);
  font-size: .92rem;
  line-height: 1.55;
}

.sto-mededeling strong {
  color: var(--ink);
  font-weight: 600;
}


/* ---------- homepage ---------- */

.sto-intro {
  border-bottom: 1px solid var(--rule);
  padding: var(--gap-xl) 0;
}

.sto-intro-inner {
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: 2rem;
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  align-items: center;
  gap: var(--gap-lg);
}

.sto-intro h1 { margin-bottom: .6rem; }

.sto-tagline {
  max-width: 46ch;
  margin: 0;
  color: var(--muted);
  font-size: clamp(1.05rem, 1rem + .3vw, 1.2rem);
  line-height: 1.6;
}

.sto-intro-art {
  justify-self: center;
  width: 100%;
  max-width: 320px;
  height: auto;
  color: var(--brand);
}

.sto-featured,
.sto-recent {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap-xl) 2rem 0;
}

/* A rule between the two groups, not just a second label. Both sections
   carry a label in the same style, and stacked one after another they read
   as one list with a subheading — which is exactly what a phone shows,
   where the sections meet at a single line of text and the column grid is
   not there to hide it. The rule sits a full --gap-xl above the label, so
   it never crowds the label's own underline. */
.sto-recent {
  border-top: 1px solid var(--rule);
  padding-bottom: var(--gap-xl);
  /* The air in front of that rule belongs HERE, not to whatever precedes
     it, because which section precedes it is decided at render time: the
     Worker deletes [affiliate-posts] and [featured-posts] whole while they
     hold no <article>, so the blogroll's neighbour is Koopgidsen on one day
     and Onderwerpen or the intro on another. One rule covers every case;
     spacing owned by a predecessor covers only that predecessor, which is
     how the guides card ended up wearing this rule as its own underline. */
  margin-top: var(--gap-lg);
}

/* Every section label on the homepage: one rule, all four selectors. The
   affiliate label used to carry its own copy of these declarations 500
   lines further down; the duplicate is folded in here, because a second
   copy is what lets this block drift out of sight. */
.sto-featured-title,
.sto-recent-title,
.sto-onderwerpen-title,
.sto-gidsen-title {
  display: block;
  margin-bottom: var(--gap);
  padding-bottom: .5rem;
  border-bottom: 2px solid var(--ink);
  font-family: var(--font-head);
  font-size: .84rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink);
}

/* Featured section has no inner wrapper: the cards are direct children
   of the <section>, so the grid lives on the section itself. */
.sto-featured {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gap-lg);
}

.sto-featured-title { grid-column: 1 / -1; margin-bottom: 0; }


/* ---------- homepage category section (variant E) ---------- */

.sto-onderwerpen {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap-xl) 2rem 0;
}

/* Two columns on desktop so the rows carry the full page width instead of
   leaving the right half empty. The last row goes ragged when the category
   count is odd, which is what the rule stack is meant to look like. */
.sto-onderwerpen-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--gap-xl);
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--rule);
}

.sto-onderwerpen-list li { border-bottom: 1px solid var(--rule); }

.sto-onderwerpen-list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .95rem .25rem;
  font-family: var(--font-head);
  font-size: 1.15rem;
  color: var(--ink);
  text-decoration: none;
  transition: color .18s ease, padding-left .18s ease;
}

.sto-onderwerpen-list a::after {
  content: "\203A";
  color: var(--accent);
  font-size: 1.4rem;
  line-height: 1;
  transition: transform .18s ease;
}

.sto-onderwerpen-list a:hover {
  color: var(--brand);
  padding-left: .55rem;
}

.sto-onderwerpen-list a:hover::after { transform: translateX(.2rem); }


/* ---------- blogroll cards ---------- */
/* Card template: flat. The dashboard emits img + h2[a] + time + p with
   no inner wrappers and no per-element classes, so everything below
   selects on element type inside .sto-kaart. */

.blog-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-lg) var(--gap);
}

.sto-kaart { position: relative; }

.sto-kaart {
  display: flex;
  flex-direction: column;
  padding: 0 0 1.35rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .2s ease, box-shadow .2s ease;
}

.sto-kaart:hover {
  border-color: var(--ink);
  box-shadow: var(--shadow);
}

.sto-kaart img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  background: var(--surface-alt);
}

.sto-kaart h2 {
  margin: 1.15rem 1.35rem .45rem;
  font-size: 1.3rem;
  line-height: 1.28;
}

.sto-kaart h2 a {
  color: var(--ink);
  text-decoration: none;
  transition: color .18s ease;
}

.sto-kaart:hover h2 a { color: var(--brand); }

/* Click-anywhere: the single title link paints an invisible target over
   the whole card, and any link inside the excerpt is lifted back above
   it so it stays individually clickable. */
.sto-kaart h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.sto-kaart p a {
  position: relative;
  z-index: 2;
}

.sto-kaart time {
  margin: 0 1.35rem;
  color: var(--muted);
  font-size: .82rem;
  letter-spacing: .04em;
}

.sto-kaart p {
  margin: .6rem 1.35rem 0;
  color: var(--muted);
  font-size: .97rem;
  line-height: 1.62;
}

.sto-kaart p + p { margin-top: .5rem; }

/* Read-more affordance. CSS only, so it survives every shape the
   dashboard regenerates. */
.sto-kaart::after {
  content: "Lees verder \2192";
  margin: 1rem 1.35rem 0;
  font-family: var(--font-head);
  font-size: .88rem;
  font-weight: 600;
  color: var(--brand);
  transition: transform .2s ease;
}

.sto-kaart:hover::after { transform: translateX(.25rem); }

/* Mixed grid: the featured card spans both columns and lays out
   image-left, text-right. The split is done with a FLOAT rather than a
   nested grid on purpose: extractFirstParagraph emits one OR two <p>
   tags, so a grid would have to pin each child to a row it cannot know
   in advance, and the second paragraph would land on top of the first.
   A float takes any number of following siblings. The card already
   carries overflow: hidden, which contains it. */
.sto-uitgelicht {
  grid-column: 1 / -1;
  /* .sto-kaart is a flex column, and a flex item cannot float. Back to
     block so the float below actually takes. The float is contained by
     the read-more ::after's clear: both, not by a block formatting
     context — .sto-kaart deliberately has no overflow rule, because one
     would clip the badge below off the card's top edge. */
  display: block;
  padding-bottom: 0;
  border-color: var(--ink);
}

/* The layout treatment below collapses on mobile — the float goes, the
   image goes full width, and all that separates a featured card from a
   normal one is a slightly larger heading, which nobody can see without a
   second card beside it. So the card also carries a badge, which reads the
   same at 1280px and at 390px and says WHY the card is different rather
   than only looking different.
   z-index 3 clears the click-anywhere stack: the h2 overlay is 1 and the
   excerpt-link lift is 2, so anything below 3 ends up under the click
   target and the badge stops being paintable over it. */
.sto-uitgelicht::before {
  content: "Aanrader";
  position: absolute;
  top: -.8rem;
  left: 1.4rem;
  z-index: 3;
  padding: .24rem .7rem;
  background: var(--brand);
  color: #fff;
  font-family: var(--font-head);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.sto-uitgelicht img {
  float: left;
  width: 44%;
  aspect-ratio: 16 / 9;
  margin-right: 2rem;
}

.sto-uitgelicht h2 { margin: 1.9rem 2rem .5rem 0; font-size: clamp(1.5rem, 1.3rem + .8vw, 1.95rem); }
.sto-uitgelicht time { margin: 0 2rem 0 0; }
.sto-uitgelicht p { margin: .7rem 2rem 0 0; font-size: 1.02rem; }
/* display: block is what makes the clear real. In a normal card the card
   is a flex column, so the ::after is blockified as a flex item — but this
   card is display: block for the float, and there a pseudo-element is
   INLINE by default, and clear does not apply to inline boxes. It only
   looked right because the sample excerpt ran long enough to push the line
   below the image; a short excerpt floated the read-more up beside it.
   The left inset matches the 1.35rem every normal card gives this element,
   so it stops touching the border. */
.sto-uitgelicht::after {
  display: block;
  clear: both;
  margin: 1.2rem 2rem 1.9rem 1.35rem;
}


/* ---------- static pages ---------- */

/* All eight run on the article shell without a sidebar, so they inherit the
   body type, the heading scale and the hairline H2 rule. Only the shapes
   these pages introduce are styled here. */

.sto-over-kop {
  display: flex;
  align-items: center;
  gap: var(--gap);
  margin-bottom: var(--gap-lg);
  padding-bottom: var(--gap);
  border-bottom: 1px solid var(--rule);
}

.sto-over-merk {
  flex-shrink: 0;
  width: 132px;
  height: 132px;
  max-width: none;
  border-radius: 50%;
  object-fit: cover;
}

.sto-over-kop h1 { margin-bottom: .5rem; }
.sto-over-kop .sto-lead { margin-bottom: 0; }

/* The contact details are a ruled list rather than a card with icons: on a
   site whose only ornament is a hairline, a boxed card would be the one
   panel with no relatives. */
.sto-contact-lijst {
  max-width: var(--measure);
  margin: var(--gap-lg) 0 var(--gap);
  border-top: 1px solid var(--rule);
}

.sto-contact-rij {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: var(--gap);
  padding: 1.1rem .1rem;
  border-bottom: 1px solid var(--rule);
}

.sto-contact-rij dt {
  font-family: var(--font-head);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.sto-contact-rij dd {
  margin: 0;
  font-size: 1.05rem;
}

.sto-contact-privacy {
  max-width: var(--measure);
  color: var(--muted);
  font-size: .92rem;
}

/* Legal pages carry a lot of H2s in a row, so the heading scale steps down
   here: at article size the page reads as a stack of titles. */
.sto-regels h2 {
  font-size: clamp(1.28rem, 1.15rem + .5vw, 1.55rem);
  margin-top: var(--gap-lg);
}

.sto-regels h3 {
  font-size: 1.08rem;
  margin-top: var(--gap);
}

.sto-regels-datum {
  margin: -.4rem 0 var(--gap);
  color: var(--muted);
  font-size: .88rem;
}

.sto-fout,
.sto-onderhoud-inner {
  max-width: 620px;
  margin-inline: auto;
  padding: var(--gap-xl) 0;
  text-align: center;
}

.sto-fout-art,
.sto-onderhoud-art {
  display: block;
  width: 100%;
  max-width: 240px;
  height: auto;
  margin: 0 auto var(--gap);
  color: var(--brand);
}

.sto-fout h1,
.sto-onderhoud h1 { margin-bottom: .8rem; }

.sto-fout > p,
.sto-onderhoud p {
  max-width: 46ch;
  margin-inline: auto;
  color: var(--muted);
}

.sto-fout-acties { margin: var(--gap-lg) 0 var(--gap); }

.sto-fout-home {
  display: inline-block;
  padding: .8rem 1.5rem;
  background: var(--ink);
  color: #fff;
  font-family: var(--font-head);
  font-size: .95rem;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background .18s ease;
}

.sto-fout-home:hover { background: var(--accent); color: #fff; }

/* The 404 reuses the header's search trigger verbatim so the global
   handler binds to it, which means it also inherits the header's white
   glyph colour. On this page it sits on white. */
.sto-fout .sto-search-trigger { color: var(--muted); }
.sto-fout .sto-search-trigger:hover { color: var(--ink); }

.sto-fout-onderwerpen {
  margin-top: var(--gap-lg);
  padding-top: var(--gap);
  border-top: 1px solid var(--rule);
}

.sto-fout-label {
  display: block;
  margin-bottom: .8rem;
  font-family: var(--font-head);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}

.sto-fout-onderwerpen ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem 1.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The 503 is served without the header and footer, so it carries its own
   centring and its own minimal footer. */
.sto-onderhoud {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  padding-inline: 1.5rem;
}

.sto-onderhoud-logo {
  width: auto;
  height: 40px;
  margin: 0 auto var(--gap-lg);
}

.sto-onderhoud-voet {
  padding-top: var(--gap-lg);
  color: var(--muted);
  font-size: .85rem;
  text-align: center;
}

.sto-onderhoud-voet p { margin: 0; color: var(--muted); }



/* ---------- affiliate: availability + pros/cons (2026-08 contract) ---------- */

/* Machine-edited: the health writer rewrites data-checked and the <time>
   text after an all-available run. One line, muted, with a brand dot. */
.sto-pf-check {
  max-width: var(--measure);
  margin: -0.6rem 0 var(--gap);
  color: var(--muted);
  font-size: .85rem;
}

.sto-pf-check::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: .45rem;
  vertical-align: 1px;
  background: var(--brand);
  border-radius: 50%;
}

.sto-pf-procon {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: 1rem 0 1.2rem;
}

.sto-pf-procon__col {
  background: var(--surface-alt);
  border-radius: var(--radius);
  padding: .75rem 1rem;
}

.sto-pf-procon__title {
  font-family: var(--font-head);
  font-size: .8rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.sto-pf-procon__col ul {
  list-style: none;
  margin: .5rem 0 0;
  padding: 0;
}

.sto-pf-procon__col li {
  display: flex;
  gap: .5rem;
  margin-bottom: .35rem;
  font-size: .95rem;
}

/* The check is the site's one hue; the cross stays ink rather than
   introducing a red the palette does not have. */
.sto-pf-procon__col--pros [aria-hidden] { color: var(--brand); font-weight: 700; }
.sto-pf-procon__col--cons [aria-hidden] { color: var(--ink); font-weight: 700; }

/* Written by the health writer in place of the buttons div's inner HTML
   when bol reports the product gone; CSS-only here. */
.sto-pf-uit {
  margin: 0;
  padding: .8rem 1.1rem;
  background: var(--surface-alt);
  border-radius: var(--radius);
  color: var(--muted);
  font-size: .95rem;
}


/* ---------- homepage: affiliate section ---------- */

.sto-gidsen {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap-xl) 2rem 0;
}

.sto-gidsen-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-lg);
}

/* Mirrors the flat blog card, deliberately under its OWN class: every
   blogroll manipulator keys on sto-kaart, and this class is what keeps
   affiliate cards out of the blogroll's dedup, sort and trim. */
.sto-gids-kaart {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0 0 1.35rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .2s ease, box-shadow .2s ease;
}

.sto-gids-kaart:hover { border-color: var(--ink); box-shadow: var(--shadow); }

.sto-gids-kaart img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  background: var(--surface-alt);
}

.sto-gids-kaart h2 {
  margin: 1.15rem 1.35rem .45rem;
  padding-bottom: .35rem;
  font-size: 1.18rem;
}

.sto-gids-kaart time {
  margin: 0 1.35rem;
  color: var(--muted);
  font-size: .85rem;
}

.sto-gids-kaart p {
  margin: .6rem 1.35rem 0;
  color: var(--muted);
  font-size: .97rem;
}

.sto-gids-kaart h2 a {
  color: var(--ink);
  text-decoration: none;
}

.sto-gids-kaart h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.sto-gids-kaart p a {
  position: relative;
  z-index: 2;
}


/* ---------- pagination (dashboard-emitted, fixed names) ---------- */

.pagination {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: .45rem;
  margin: var(--gap-xl) 0 0;
  padding: 0;
  list-style: none;
}

.pagination a,
.pagination .current {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 42px;
  height: 42px;
  padding: 0 .8rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-family: var(--font-head);
  font-size: .98rem;
  text-decoration: none;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}

.pagination a {
  color: var(--ink);
  background: var(--surface);
}

.pagination a:hover {
  color: var(--brand);
  border-color: var(--ink);
  background: var(--surface-alt);
}

.pagination .current {
  color: #fff;
  background: var(--brand);
  border-color: var(--brand);
  font-weight: 600;
}

.pagination a[rel="prev"],
.pagination a[rel="next"] {
  padding-inline: 1.15rem;
  font-weight: 600;
}


/* ---------- article layout ---------- */

.sto-wrapper {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap-lg) 2rem var(--gap-xl);
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--gap-xl);
  align-items: start;
}

/* Static pages, affiliate posts, 404 and search have no sidebar. */
.sto-wrapper--vol { grid-template-columns: minmax(0, 1fr); }
.sto-wrapper--vol .sto-artikel { max-width: 780px; margin-inline: auto; }

.sto-wrapper > main { min-width: 0; }
.sto-artikel { min-width: 0; }

.sto-hero {
  margin: 0 0 var(--gap);
  line-height: 0;
}

.sto-hero img {
  width: 100%;
  height: auto;
  border-radius: var(--hero-radius);
}

.sto-meta {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  margin: 0 0 var(--gap-lg);
  padding-bottom: var(--gap);
  border-bottom: 1px solid var(--rule);
}

.sto-meta-rij {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem;
}

.sto-meta nav {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

.sto-cat {
  display: inline-block;
  padding: .28rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--surface-alt);
  color: var(--brand-deep);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-decoration: none;
}

.sto-cat:hover { border-color: var(--brand); background: var(--surface); color: var(--brand-deep); }

/* The label carries its own colon in the markup, so the gap here is a word
   space and nothing more. */
.sto-datum,
.sto-auteur {
  display: inline-flex;
  align-items: baseline;
  gap: .3rem;
  font-size: .88rem;
  color: var(--ink);
}

.sto-datum-label,
.sto-auteur-label {
  color: var(--muted);
  font-size: .82rem;
}

.sto-lead {
  font-size: 1.12rem;
  line-height: 1.66;
  color: var(--ink);
}


/* ---------- table of contents ---------- */

.sto-toc {
  margin: 0 0 var(--gap-lg);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

.sto-toc-toggle {
  display: flex;
  align-items: center;
  gap: .6rem;
  width: 100%;
  padding: .85rem 1.1rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-head);
  font-size: 1rem;
  text-align: left;
}

.sto-toc.is-interactive .sto-toc-toggle { cursor: pointer; }

.sto-toc-icon { color: var(--brand); line-height: 0; }
.sto-toc-title { flex: 1; font-weight: 600; }

.sto-toc-chevron {
  color: var(--muted);
  transition: transform .22s ease;
}

.sto-toc-toggle[aria-expanded="true"] .sto-toc-chevron { transform: rotate(180deg); }

.sto-toc-panel { padding: 0 1.1rem 1rem; }
.sto-toc-panel[hidden] { display: none; }

.sto-artikel .sto-toc-panel ul,
.sto-toc-panel ul {
  margin: 0;
  padding-left: 1.15rem;
  list-style: none;
  counter-reset: toc;
}

.sto-artikel .sto-toc-panel li { margin: .3rem 0; }

.sto-toc-panel > ul > li { counter-increment: toc; }

.sto-toc-panel > ul > li > a::before {
  content: counter(toc) ". ";
  color: var(--muted);
}

.sto-toc-panel li { margin: .3rem 0; }

.sto-toc-panel a {
  color: var(--ink);
  font-size: .95rem;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.sto-toc-panel a:hover { color: var(--brand); border-bottom-color: currentColor; }

.sto-artikel .sto-toc-panel ul ul,
.sto-toc-panel ul ul {
  padding-left: 1rem;
  margin-top: .2rem;
  margin-bottom: 0;
}

.sto-toc-panel ul ul a { font-size: .9rem; color: var(--muted); }


/* ---------- article body ---------- */

.sto-artikel > p,
.sto-artikel > ul,
.sto-artikel > ol,
.sto-artikel > h2,
.sto-artikel > h3,
.sto-artikel > h4 { max-width: var(--measure); }

.sto-artikel ul,
.sto-artikel ol {
  margin: 0 0 1.3em;
  padding-left: 1.35rem;
}

.sto-artikel li { margin-bottom: .45em; }

.sto-artikel ul li::marker { color: var(--brand); }
.sto-artikel ol li::marker { color: var(--brand); font-weight: 600; }

.sto-artikel blockquote {
  margin: var(--gap) 0;
  padding-left: 1.2rem;
  border-left: 3px solid var(--brand);
  color: var(--muted);
  font-style: italic;
}

.sto-artikel strong { font-weight: 600; }

/* Editorial aside inside the article body. */
.sto-notitie {
  max-width: 66ch;
  margin: var(--gap) 0 var(--gap-lg);
  padding: .9rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  color: var(--muted);
  font-size: .92rem;
  line-height: 1.6;
}

.sto-notitie p:last-child { margin-bottom: 0; }
.sto-notitie strong { color: var(--ink); }

/* Quote body in the BODY face, italic: IBM Plex Sans ships a real drawn
   italic, which is why it was picked. The old rule set the quote in Oswald,
   and Oswald has no italic — any slant on it would be synthesized, and at
   body size the condensed face reads as a heading that lost its case. The
   cite below keeps the upright weight, so attribution and quote separate
   by style rather than by size. */
.sto-citaat {
  max-width: var(--measure);
  margin: var(--gap-lg) 0;
  padding: 1.35rem 1.5rem;
  border: 1px solid var(--rule);
  border-top: 3px solid var(--brand);
  border-radius: var(--radius);
  background: var(--surface-alt);
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.08rem;
  line-height: 1.6;
}

.sto-citaat p { margin: 0 0 .5rem; }
.sto-citaat p:last-child { margin-bottom: 0; }

.sto-citaat cite {
  display: block;
  margin-top: .7rem;
  color: var(--brand);
  font-family: var(--font-body);
  font-size: .875rem;
  font-style: normal;
  font-weight: 600;
}

/* Table container. The LLM wraps every <table> in this class so wide
   tables scroll instead of being cut off. */
.sto-tabel {
  max-width: var(--measure);
  margin: 0 0 var(--gap-lg);
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.sto-tabel table {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font-size: .95rem;
}

.sto-tabel th,
.sto-tabel td {
  padding: .7rem .9rem;
  text-align: left;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

.sto-tabel th {
  background: var(--surface-alt);
  font-family: var(--font-head);
  font-weight: 600;
  white-space: nowrap;
}

.sto-tabel tbody tr:last-child td { border-bottom: 0; }
.sto-tabel tbody tr:nth-child(even) { background: var(--surface-alt); }

/* FAQ accordion. Every question is a <details> whose heading lives
   inside the <summary>; H3 rows are SIBLINGS of their H2 row, never
   nested, so the grouping is carried visually rather than structurally.
   No JavaScript anywhere: native <details> does the whole job. */
.sto-vragen {
  max-width: var(--measure);
  margin: var(--gap-xl) 0 0;
  border-top: 1px solid var(--rule);
}

.sto-vragen-item { border-bottom: 1px solid var(--rule); }

.sto-vragen-item > summary {
  display: flex;
  align-items: baseline;
  gap: .8rem;
  padding: .95rem .2rem;
  cursor: pointer;
  list-style: none;
  transition: color .18s ease;
}

/* Drop the native disclosure triangle; the chevron below replaces it. */
.sto-vragen-item > summary::-webkit-details-marker { display: none; }
.sto-vragen-item > summary::marker { content: ""; }

/* Article heading margins are tuned for body flow and wreck a row
   label, so they are reset here rather than worked around. The h2 rule
   underneath is dropped too: in a flex row the heading is only as wide as
   its text, so the rule would stop halfway and fight the row divider. */
.sto-vragen-item > summary h2,
.sto-vragen-item > summary h3 {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 1.12rem;
  line-height: 1.35;
  font-weight: 600;
}

/* H3 rows sit a step smaller and indented, so a sub-question still
   reads as belonging to the question above it. */
.sto-vragen-item > summary h3 { font-size: 1rem; color: var(--muted); }
.sto-vragen-item:has(> summary h3) > summary { padding-left: 1.4rem; }
/* The answer has to follow the question in. It is a bare <p> — that is the
   platform's FAQ contract (<details><summary><h2></summary><p>), and the
   FAQ-refresh endpoint rewrites those paragraphs in place — so this matches
   the same "everything that is not the summary" shape the spacing rule
   below uses. An earlier version targeted an answer CLASS, which nothing
   emits, so the question indented and its answer stayed flush left. */
.sto-vragen-item:has(> summary h3) > *:not(summary) { padding-left: 1.4rem; }

.sto-vragen-item > summary::after {
  content: "\25BE";
  margin-left: auto;
  color: var(--brand);
  font-size: .85rem;
  line-height: 1.6;
  transition: transform .2s ease;
}

.sto-vragen-item[open] > summary::after { transform: rotate(180deg); }

.sto-vragen-item > summary:hover { color: var(--brand); }
.sto-vragen-item > summary:hover h3 { color: var(--brand); }

.sto-vragen-item > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 2px;
}

/* Padding on the answer, not on the summary, so an open row and a
   closed row keep the same header height. */
.sto-vragen-item > *:not(summary) {
  margin: 0 0 .9rem;
  padding-right: 2rem;
  color: var(--muted);
  font-size: .97rem;
  line-height: 1.62;
}

.sto-vragen-item > *:not(summary):last-child { margin-bottom: 1.1rem; }


/* ---------- share buttons (outlined) ---------- */

.sto-deel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .55rem;
  margin: var(--gap-xl) 0 0;
  padding-top: var(--gap);
  border-top: 1px solid var(--rule);
}

.sto-deel-knop {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-width: 44px;
  height: 44px;
  padding: 0 .9rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  font-size: .85rem;
  text-decoration: none;
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, background .18s ease;
}

.sto-deel-knop:hover,
.sto-deel-knop:focus-visible {
  color: var(--brand);
  border-color: var(--ink);
  background: var(--surface-alt);
}

.sto-deel-knop svg { width: 18px; height: 18px; }

.sto-deel-knop.is-copied {
  color: var(--accent);
  border-color: var(--accent);
}


/* ---------- author box ---------- */

.sto-schrijver {
  margin: var(--gap-xl) 0 0;
  padding: 1.6rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}

.sto-schrijver-label {
  display: block;
  margin-bottom: .9rem;
  font-family: var(--font-head);
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brand);
}

.sto-schrijver-inner {
  display: flex;
  align-items: flex-start;
  gap: 1.2rem;
}

/* The <a> is the flex item, not the <img>, so it needs the shrink guard.
   Without it the global img max-width:100% squeezes the avatar sideways on
   a narrow viewport while its fixed height holds. */
.sto-schrijver-avatar-link {
  flex-shrink: 0;
  line-height: 0;
}

.sto-schrijver-avatar {
  width: 72px;
  height: 72px;
  max-width: none;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--rule);
}

.sto-schrijver-naam {
  display: inline-block;
  margin-bottom: .25rem;
  font-family: var(--font-head);
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
}

.sto-schrijver-naam:hover { color: var(--brand); }

.sto-schrijver-desc {
  margin: 0;
  color: var(--muted);
  font-size: .95rem;
  line-height: 1.6;
}


/* ---------- sidebar (right) ---------- */

/* Stretch to the row height even though the grid is align-items: start.
   The newsletter block below is sticky, and a sticky element can only
   slide inside its own parent's box — left at start the <aside> is only as
   tall as its content (measured: 557px against a 3792px article), so the
   block scrolled away with the column instead of following the reader. */
.sto-zijbalk {
  align-self: stretch;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
}

.sto-zijbalk-sectie {
  padding-bottom: var(--gap);
  border-bottom: 1px solid var(--rule);
}

.sto-zijbalk-logo {
  display: block;
  max-width: 150px;
  margin-bottom: .9rem;
}

.sto-zijbalk-over {
  margin: 0;
  color: var(--muted);
  font-size: .92rem;
  line-height: 1.62;
}

.sto-zijbalk-sticky { position: sticky; top: 1.5rem; }

.sto-zijbalk-cta {
  padding: 1.4rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
  text-align: center;
}

.sto-zijbalk-cta-img {
  display: block;
  width: 96px;
  height: auto;
  margin: 0 auto .7rem;
  color: var(--brand);
}

.sto-zijbalk-titel {
  display: block;
  margin-bottom: .35rem;
  font-family: var(--font-head);
  font-size: 1.15rem;
  font-weight: 600;
}

.sto-zijbalk-cta p {
  margin: 0 0 .9rem;
  color: var(--muted);
  font-size: .9rem;
  line-height: 1.55;
}

.sto-zijbalk-form {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}


/* ---------- forms and buttons ---------- */

.sto-zijbalk-input,
.sto-cta-input {
  width: 100%;
  padding: .68rem .85rem;
  font-family: var(--font-body);
  font-size: .95rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.sto-zijbalk-input::placeholder,
.sto-cta-input::placeholder { color: var(--muted); }

.sto-zijbalk-input:focus,
.sto-cta-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.sto-zijbalk-knop,
.sto-cta-knop {
  padding: .72rem 1.4rem;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: #fff;
  font-family: var(--font-head);
  font-size: .92rem;
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease;
}

.sto-zijbalk-knop:hover,
.sto-cta-knop:hover {
  background: var(--accent);
  border-color: var(--accent);
}

.sto-nieuwsbrief-ok {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .35rem;
  padding: 1.1rem .4rem;
  text-align: center;
}

.sto-nieuwsbrief-ok-icon { color: var(--accent); }

.sto-nieuwsbrief-ok-titel {
  font-family: var(--font-head);
  font-size: 1.08rem;
  font-weight: 600;
  color: var(--ink);
}

.sto-nieuwsbrief-ok-body {
  margin: 0;
  color: var(--muted);
  font-size: .9rem;
  line-height: 1.55;
}


/* ---------- newsletter CTA banner (split layout) ---------- */

.sto-cta {
  border-top: 1px solid var(--rule);
  background: var(--surface-alt);
}

.sto-cta-inner {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap-lg) 2rem;
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  align-items: center;
  gap: var(--gap-lg);
}

.sto-cta-img {
  width: 100%;
  height: auto;
  color: var(--brand);
}

.sto-cta-titel {
  display: block;
  margin-bottom: .3rem;
  font-family: var(--font-head);
  font-size: clamp(1.35rem, 1.2rem + .6vw, 1.7rem);
  font-weight: 600;
}

.sto-cta-content p {
  max-width: 56ch;
  margin: 0 0 1rem;
  color: var(--muted);
}

.sto-cta-form {
  display: flex;
  flex-wrap: wrap;
  gap: .55rem;
  max-width: 480px;
}

.sto-cta-form .sto-cta-input { flex: 1 1 220px; width: auto; }


/* ---------- footer (large) ---------- */

.sto-voet {
  background: var(--surface-alt);
  color: var(--ink);
  border-top: 1px solid var(--rule);
}

.sto-voet a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--rule); }
.sto-voet a:hover { color: var(--accent); text-decoration-color: currentColor; }

.sto-voet-inner {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap-xl) 2rem var(--gap-lg);
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: var(--gap-lg);
}

.sto-voet-logo {
  max-width: 160px;
  height: auto;
  margin-bottom: 1rem;
}

.sto-voet-desc {
  margin: 0;
  max-width: 42ch;
  color: var(--muted);
  font-size: .92rem;
  line-height: 1.62;
}

.sto-voet-titel {
  display: block;
  margin-bottom: .8rem;
  font-family: var(--font-head);
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
  padding-bottom: .4rem;
}

.sto-voet-links {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sto-voet-links li { margin-bottom: .5rem; }
.sto-voet-kolom p { margin: 0 0 .5rem; font-size: .95rem; }

.sto-sociaal {
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
  margin-top: 1.1rem;
}

.sto-sociaal-icoon {
  width: 34px;
  height: 34px;
  padding: 7px;
  border: 1px solid var(--rule);
  color: var(--muted);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  transition: color .18s ease, border-color .18s ease;
}

.sto-sociaal a:hover .sto-sociaal-icoon {
  color: var(--accent);
  border-color: var(--accent);
}

.sto-voet-onder {
  max-width: var(--page);
  margin-inline: auto;
  padding: var(--gap) 2rem var(--gap-lg);
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
  font-size: .86rem;
  color: var(--muted);
}

.sto-juridisch {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem;
}


/* ---------- back to top ---------- */

.sto-btt {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: #fff;
  box-shadow: var(--shadow-lift);
  opacity: 0;
  pointer-events: none;
  transform: translateY(6px);
  transition: opacity .24s ease, transform .24s ease, background .18s ease;
  cursor: pointer;
}

.sto-btt svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sto-btt-zichtbaar {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.sto-btt:hover { background: var(--accent); border-color: var(--accent); }


/* ---------- cookie notice ---------- */

.sto-cookie {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  z-index: 250;
  width: min(680px, calc(100vw - 40px));
  padding: 1.1rem 1.3rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-lift);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .8rem 1.2rem;
  font-size: .9rem;
  color: var(--muted);
}

.sto-cookie[hidden] { display: none; }
.sto-cookie p { flex: 1 1 280px; margin: 0; line-height: 1.55; }

.sto-cookie-accept,
.sto-cookie-decline {
  padding: .5rem 1.1rem;
  border-radius: var(--radius);
  font-family: var(--font-head);
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
}

.sto-cookie-accept {
  border: 1px solid var(--brand);
  background: var(--brand);
  color: #fff;
}

.sto-cookie-accept:hover { background: var(--brand-deep); border-color: var(--brand-deep); }

.sto-cookie-decline {
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--muted);
}

.sto-cookie-decline:hover { color: var(--ink); border-color: var(--muted); }


/* ---------- category and static pages ---------- */

.sto-cat-intro {
  max-width: var(--measure);
  margin: 0 0 var(--gap-xl);
  color: var(--ink);
}

.sto-cat-intro p:last-child { margin-bottom: 0; }

.sto-fout {
  max-width: 640px;
  margin-inline: auto;
  padding: var(--gap-xl) 2rem;
  text-align: center;
}

.sto-fout p { color: var(--muted); }


/* ---------- affiliate: disclosure aside ---------- */

.sto-disclo {
  max-width: var(--measure);
  margin: 0 0 var(--gap-lg);
  padding: 1rem 1.2rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
  color: var(--muted);
  font-size: .89rem;
  line-height: 1.58;
}

.sto-disclo details summary { list-style: none; }
.sto-disclo details summary::-webkit-details-marker { display: none; }

.sto-disclo-summary { display: block; margin-bottom: .35rem; }
.sto-disclo summary strong { color: var(--ink); }

/* Body font at normal weight, sized like the aside around it: this is a
   control, not a heading, and it only has to be findable. In the condensed
   heading face at 600 it read as bold and pulled harder than the notice it
   opens. The accent colour and the underline carry the affordance, the same
   way the slider jumplink does. */
.sto-disclo-toggle {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--accent);
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: 400;
}

.sto-disclo-label { text-decoration: underline; text-underline-offset: .16em; }
.sto-disclo.is-interactive summary { cursor: pointer; }
.sto-disclo.is-interactive .sto-disclo-toggle { cursor: pointer; }
.sto-disclo-toggle:hover { color: var(--brand-deep); }
.sto-disclo-chevron { font-size: .72rem; line-height: 1; }

.sto-disclo-vol { margin-top: .7rem; }
.sto-disclo-vol p:last-child { margin-bottom: 0; }


/* ---------- affiliate: product summary slider ---------- */

.sto-pn-grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(260px, 1fr);
  gap: var(--gap);
  margin: 0 0 var(--gap);
  padding-bottom: .5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}

.sto-pn-card {
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  padding: 1.2rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
}

.sto-pn-card__badge {
  align-self: center;
  margin-bottom: .7rem;
  padding: .22rem .7rem;
  border-radius: var(--radius-pill);
  background: var(--brand);
  color: #fff;
  font-family: var(--font-head);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.sto-pn-card__header { display: flex; justify-content: center; }

/* No border and no shadow: the product photo should sit on the card, not
   in a box drawn around it. The white background is NOT decoration and
   stays — product JPEGs ship with a baked-in white background, so a
   container in any other colour frames the cut-out in a visible rectangle. */
.sto-pn-card__image {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 4 / 3;
  margin-bottom: .8rem;
  padding: .6rem;
  background: #fff;
  overflow: hidden;
}

.sto-pn-card__image img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* The slider image is wrapped in a jumplink to the matching review
   card. Without display:contents the anchor becomes an inline box
   between the flex container and the img, and the centering breaks. */
.sto-pn-card__image a { display: contents; }

.sto-pn-card__title {
  margin: 0 0 .35rem;
  font-family: var(--font-head);
  font-size: 1.06rem;
  font-weight: 600;
  line-height: 1.3;
}

.sto-pn-card__desc {
  margin: 0 0 .9rem;
  color: var(--muted);
  font-size: .9rem;
  line-height: 1.55;
}

.sto-pn-button,
.sto-pf-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  width: 100%;
  padding: .68rem 1.1rem;
  border: 1px solid var(--cta);
  border-radius: var(--radius);
  background: var(--cta);
  color: #fff;
  font-family: var(--font-head);
  font-size: .95rem;
  font-weight: 600;
  text-decoration: none;
  transition: background .18s ease, border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

.sto-pn-button:hover,
.sto-pf-button:hover {
  background: var(--cta-deep);
  border-color: var(--cta-deep);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

/* Plain text, and it must lose to the CTA above it. This is an in-page
   scroll to the matching review card — a navigation aid, not an action —
   and the product image already links to the same anchor, so the card
   offers two routes and only one of them has to be findable. Never bold
   and never filled: bold text under a filled button is two loud things
   stacked, and the eye takes the lower one because it comes last. */
.sto-pn-button--jumplink {
  width: auto;
  margin-top: .55rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand);
  font-family: var(--font-body);
  font-size: .9rem;
  font-weight: 400;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.sto-pn-button--jumplink:hover {
  background: none;
  color: var(--brand-deep);
  transform: none;
  box-shadow: none;
}

.sto-pn-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .9rem;
  margin-bottom: var(--gap-lg);
}

/* Square, like every other button on the site. These were the only round
   controls outside the dot indicators, and a circle on a zero-radius site
   reads as imported. The dots stay round because a dot is a dot. */
.sto-pn-arrow {
  width: 38px;
  height: 38px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.sto-pn-arrow:hover { color: var(--brand); border-color: var(--brand); }

.sto-pn-dots { display: flex; gap: .4rem; }

.sto-pn-dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--rule);
  cursor: pointer;
  transition: background .18s ease, transform .18s ease;
}

.sto-pn-dot.is-active { background: var(--brand); transform: scale(1.25); }


/* ---------- affiliate: review cards ---------- */

/* One bounded block per product: badge, title, media row, pros/cons grid,
   the two review paragraphs and the CTA all live inside this article. The
   two-column arrangement moved down to __media, so the grid below the
   media row spans the full card width. The badge is absolutely positioned
   and stays outside the flow. */
.sto-pf-card {
  position: relative;
  max-width: var(--measure);
  margin: var(--gap-lg) 0 var(--gap);
  padding: 1.6rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  /* White, not the alt band. The product image container has to be white
     because product JPEGs carry a baked-in white background, so a tinted
     card leaves that container sitting on it as a visible patch. Matching
     the card to it makes the seam disappear, which is what the slider
     already does. The hairline border and the overhanging badge are what
     make this read as a card. */
  background: var(--surface);
}

/* NOTHING between two cards. The card used to be a looser shape with its
   prose sitting outside it, and the 1px line in the gap was what said where
   one product ended. The media-row card closed that gap itself: one bounded
   article with its own border and a 3rem gap around it. A line on top of
   that is a second separator competing with a boundary that already reads.
   If products ever stop reading as separate blocks, widen the gap or
   strengthen the border here rather than putting the line back. */

.sto-pf-card--top { border-color: var(--ink); }

.sto-pf-card__badge {
  position: absolute;
  top: -.85rem;
  left: 1.6rem;
  padding: .25rem .8rem;
  border-radius: var(--radius-pill);
  background: var(--brand);
  color: #fff;
  font-family: var(--font-head);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.sto-pf-card h2,
.sto-pf-card__title {
  margin: .3rem 0 .4rem;
  font-size: 1.35rem;
}

/* The jumplink has to land on the CARD, not on a bare title with the badge
   already scrolled off the top. The id sits on the <span>, so the span's
   offset is the one that counts, not the card's: the contract targets the
   card class, but scroll-margin only applies to the element the fragment
   actually resolves to. The span now sits directly under the badge, so it
   only has to clear the card padding (25.6px) and the badge overhang
   (13.6px); 4rem covers both and leaves air. */
.sto-pf-card h2,
.sto-pf-card__title span { scroll-margin-top: 4rem; }

/* Media row: product image left in a fixed square box, its numbers right.
   The reader compares the thing and its specs in one glance instead of
   scrolling past a wide banner to reach them, and the pros/cons grid below
   gets the full card width instead of half of it. */
.sto-pf-card__media {
  --pf-image: 180px;
  display: grid;
  grid-template-columns: var(--pf-image) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
  margin-top: 1rem;
}

/* Square and object-fit: contain are load-bearing, not decoration. Product
   photos are fitted inside 800x800 by the pipeline and genuinely differ in
   aspect ratio, so the fixed box is what keeps a run of cards aligned.
   Never cover: it crops the product.
   No border and no shadow, per the decision taken for the slider and the
   product boxes on this site. The reference CSS draws a rule around the
   box; here the card is already white, so the box would only add a frame
   around white on white. */
.sto-pf-card__image {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--pf-image);
  aspect-ratio: 1;
  padding: .5rem;
  background: #fff;
  overflow: hidden;
}

.sto-pf-card__image img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.sto-pf-card__image a { display: contents; }

/* Rating and the optional price tier share one line. */
.sto-pf-card__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .9rem;
}

.sto-pf-card__meta .sto-pf-rating { margin-bottom: 0; }

/* Segment, never an amount: filled marks count where the product sits in
   this article's own price range, and the aria-label names the segment in
   words so the meaning does not depend on counting euro signs. */
/* Body font, not the condensed heading face: four euro signs in Oswald run
   into each other and read as a smudge instead of as four countable marks.
   The tracking is what separates the filled group from the dimmed one, so
   it is doing real work rather than styling. */
.sto-pf-prijs {
  font-family: var(--font-body);
  font-size: 1rem;
  letter-spacing: .16em;
}

.sto-pf-prijs__vol { color: var(--ink); font-weight: 700; }
.sto-pf-prijs__leeg { color: var(--rule); font-weight: 700; }

.sto-pf-card__bestvoor {
  margin: .7rem 0 0;
  color: var(--muted);
  font-size: .95rem;
}

.sto-pf-card__bestvoor strong { color: var(--ink); }

/* Spec sheet, not prose: no bullets, no hanging indent, tight leading, and
   values without a closing period. Scoped under .sto-artikel because the
   generic `.sto-artikel ul` rule further up carries the same specificity as
   a bare class and would otherwise win on source order, putting the body
   list's padding and bottom margin back. */
.sto-artikel .sto-pf-card__specs {
  margin: .75rem 0 0;
  padding: 0;
  list-style: none;
  font-size: .95rem;
}

.sto-artikel .sto-pf-card__specs li { margin-bottom: .2rem; }

.sto-pf-card__review {
  margin: 0 0 var(--gap-sm);
  max-width: none;
}

.sto-pf-card__review + .sto-pf-card__review { margin-bottom: var(--gap); }

.sto-pf-card__buttons {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
}

.sto-pf-card__buttons .sto-pf-button { width: auto; min-width: 190px; }

/* Plain inline flow, not a flex row. Centring two line boxes of different
   heights left the number sitting optically high, and the spec's shape
   does not need it. */
.sto-pf-rating,
.sto-pn-rating {
  margin-bottom: .8rem;
}

/* letter-spacing 0 and line-height 1 are both load-bearing. Any tracking
   drifts the filled track away from the empty one by a fraction of a star
   and adds a trailing letter-space that the width % overshoots into; the
   inherited body line-height gave a 28px box around a 16px glyph, so the
   absolutely positioned fill landed where the box was rather than where
   the glyphs are. */
.sto-pf-rating__stars,
.sto-pn-rating__stars {
  position: relative;
  display: inline-block;
  color: var(--star-track);
  letter-spacing: 0;
  line-height: 1;
}

.sto-pf-rating__stars-filled,
.sto-pn-rating__stars-filled {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  overflow: hidden;
  white-space: nowrap;
  color: var(--star);
}

/* The visible number is dropped on this site, on both card types, so no
   article should emit this span. The rule stays as a guard: an older or
   hand-edited article that still carries one gets the spec's treatment
   instead of raw body text. */
.sto-pf-rating__text,
.sto-pn-rating__text {
  margin-left: .35em;
  color: var(--muted);
  font-size: .9em;
}

/* Sized for U+2726, which is noticeably smaller than U+2605 at the same
   font-size. The five-mark strip lands at roughly the width the cards were
   drawn around; changing the mark means re-tuning these and re-checking a
   4.5 rendering. */
.sto-pn-rating--compact { margin-bottom: .5rem; }
.sto-pn-rating--compact .sto-pn-rating__stars { font-size: 1.15rem; }
.sto-pn-rating--compact .sto-pn-rating__text { font-size: .8rem; }
.sto-pf-rating .sto-pf-rating__stars { font-size: 1.6rem; }
.sto-pf-rating .sto-pf-rating__text { font-size: 1rem; }

.sto-af-sluit {
  max-width: var(--measure);
  margin: var(--gap-xl) 0 0;
  padding: 1.4rem 1.6rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--brand);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-alt);
}

.sto-af-sluit-titel {
  display: block;
  margin-bottom: .5rem;
  font-family: var(--font-head);
  font-size: 1.15rem;
  font-weight: 600;
}

/* The links are a <ul>, never prose — updateClosingLinks rebuilds exactly
   this list and keeps whatever precedes it as the header. The marker is
   dropped for a chevron so a two-item list does not read as a body list. */
.sto-af-sluit ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.sto-af-sluit li {
  padding: .42rem 0;
  border-top: 1px solid var(--rule);
}

.sto-af-sluit li:first-child { border-top: 0; padding-top: 0; }
.sto-af-sluit li:last-child { padding-bottom: 0; }

.sto-af-sluit li a {
  display: inline-flex;
  align-items: baseline;
  gap: .45rem;
  color: var(--brand);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.sto-af-sluit li a::before {
  content: "\203A";
  color: var(--accent);
  font-size: 1.15rem;
  line-height: 1;
}

.sto-af-sluit li a:hover { color: var(--brand-deep); border-bottom-color: currentColor; }

.sto-af-sluit p:last-child { margin-bottom: 0; }


/* ---------- mobile ---------- */

@media (max-width: 768px) {
  :root {
    --gap-lg: 2rem;
    --gap-xl: 3rem;
  }

  body { padding-top: var(--bar); }

  h2, h3, h4 { scroll-margin-top: calc(var(--bar) + 1rem); }

  .sto-header-inner,
  .sto-mededeling-inner,
  .sto-intro-inner,
  .sto-featured,
  .sto-recent,
  .sto-onderwerpen,
  .sto-wrapper,
  .sto-cta-inner,
  .sto-voet-inner,
  .sto-voet-onder { padding-inline: 1.15rem; }

  .sto-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    transition: transform .3s ease;
    will-change: transform;
  }

  .sto-header--hidden { transform: translateY(-100%); }
  .sto-header--scrolled { box-shadow: var(--shadow); }

  .sto-header-inner {
    height: var(--bar);
    padding: 0 1.15rem;
    flex-direction: row;
    justify-content: space-between;
    gap: 0;
  }

  .sto-header-top {
    width: 100%;
    grid-template-columns: 1fr auto;
    height: 100%;
  }

  .sto-logo { grid-column: 1; justify-self: start; }
  .sto-logo img { height: 34px; }
  .sto-header-tools { grid-column: 2; }
  .sto-menu-toggle { display: inline-flex; }
  .sto-nav { display: none; }

  .sto-mobile-nav:not(.hidden) {
    display: block;
    position: absolute;
    top: var(--bar);
    left: 0;
    right: 0;
    background: var(--ink);
    box-shadow: var(--shadow-lift);
    max-height: calc(100vh - var(--bar));
    overflow-y: auto;
  }

  .sto-mededeling-inner { padding-block: .8rem; }
  .sto-mededeling p { font-size: .88rem; }

  .sto-intro { padding: var(--gap-lg) 0; }
  .sto-intro-inner { grid-template-columns: 1fr; gap: var(--gap); }
  .sto-intro-art { max-width: 200px; order: -1; justify-self: start; }

  .blog-list { grid-template-columns: 1fr; gap: var(--gap); }

  .sto-onderwerpen-list { grid-template-columns: minmax(0, 1fr); }

  .sto-gidsen { padding-inline: 1.15rem; }
  .sto-gidsen-grid { grid-template-columns: minmax(0, 1fr); gap: var(--gap); }
  .sto-pf-procon { grid-template-columns: 1fr; }

  /* One column on mobile, so the float is dropped and the card goes
     back to the same vertical stack as every other card. */
  .sto-uitgelicht { padding-bottom: 1.35rem; }
  .sto-uitgelicht img { float: none; width: 100%; height: auto; min-height: 0; max-height: none; margin-right: 0; aspect-ratio: 16 / 9; }
  .sto-uitgelicht h2 { margin: 1.15rem 1.35rem .45rem; }
  .sto-uitgelicht time { margin: 0 1.35rem; }
  .sto-uitgelicht p { margin: .6rem 1.35rem 0; font-size: .97rem; }
  .sto-uitgelicht::after { margin: 1rem 1.35rem 0; }

  .sto-wrapper { grid-template-columns: 1fr; gap: var(--gap-lg); }
  .sto-zijbalk { display: none; }

  .sto-meta-rij { flex-direction: column; align-items: flex-start; gap: .35rem; }

  .sto-over-kop { flex-direction: column; align-items: flex-start; gap: var(--gap-sm); }
  .sto-over-merk { width: 96px; height: 96px; }
  .sto-contact-rij { grid-template-columns: minmax(0, 1fr); gap: .2rem; }
  .sto-onderhoud-logo { height: 32px; }

  .sto-search-panel { margin-top: 4vh; max-width: none; border-radius: 0; }
  .sto-search-results { max-height: 68vh; }

  .sto-cta-inner { grid-template-columns: 1fr; gap: var(--gap); }
  .sto-cta-img { max-width: 120px; }
  .sto-cta-form { max-width: none; }
  .sto-cta-form .sto-cta-knop { width: 100%; }

  .sto-voet-inner { grid-template-columns: 1fr; gap: var(--gap-lg); }
  .sto-voet-onder { flex-direction: column; align-items: flex-start; }

  .sto-btt { right: 16px; bottom: 16px; }

  .sto-pf-card { padding: 1.2rem; }

  /* The media row stacks with the image on top, centred rather than
     hugging the left edge, and a little larger than the desktop box now
     that it has the full width to sit in. */
  .sto-pf-card__media { --pf-image: 220px; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
  .sto-pf-card__image { margin-inline: auto; }

  /* The anchor span sits directly under the badge here too, so it only has
     to clear the fixed header plus the card padding and the badge
     overhang. The old 18.5rem offset belonged to the retired layout, where
     the product image stood above the span. */
  .sto-pf-card h2,
  .sto-pf-card__title span { scroll-margin-top: calc(var(--bar) + 4rem); }
  .sto-pf-card__buttons .sto-pf-button { width: 100%; min-width: 0; }
  .sto-pn-grid { grid-auto-columns: minmax(240px, 82%); }
}

@media (min-width: 769px) {
  .sto-mobile-nav { display: none; }
}

/* Intermediate band between the mobile breakpoint and a comfortable
   desktop. The article grid keeps its 300px sidebar and 5rem gutter all
   the way down to 769px, which pinches the content column to ~450px at
   900px wide — a four-line H1 on a "tablet" that is really any narrow
   window. The single 768px breakpoint is untouched; this only relaxes
   the two widths that were sized for 1280. */
@media (min-width: 769px) and (max-width: 1080px) {
  .sto-wrapper {
    grid-template-columns: minmax(0, 1fr) 250px;
    gap: var(--gap-lg);
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
