/* BuyRight Notes storefront page styles. Imports brand/brand.css first (tokens, buttons, cards, reels). */

body { min-height: 100%; }
.lampfield { position: fixed; inset: 0 0 auto 0; height: 62vh; background: var(--lamp); pointer-events: none; z-index: 0; }
.page { position: relative; z-index: 1; max-width: 760px; margin: 0 auto; padding: 0 0 calc(96px + env(safe-area-inset-bottom, 0px)); }

/* Top bar */
.top {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: calc(10px + env(safe-area-inset-top, 0px)) var(--gutter) 10px;
  background: color-mix(in srgb, var(--ink-950) 78%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.top .brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--text); font-family: var(--font-display); font-size: 1.15rem; letter-spacing: -0.01em; }
.top .brand svg { width: 28px; height: 28px; flex: none; } /* the mark keeps its size when the name wraps (it shrank with it, to a dot at 1080px) */
.top .brand em { font-style: italic; font-weight: 400; color: var(--text-2); }
.top .spacer { flex: 1; }
/* Internal mode marker: only our own browsers ever see it. */
.internal-chip { font: 600 var(--fs-xs)/1 var(--font-ui); color: var(--text-2); text-decoration: none; padding: 8px 10px; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1.5px var(--accent); white-space: nowrap; }

/* Category bar: a swipeable row of chips inside the sticky header. The current section is highlighted
   (bone text, ember outline); the solid ember fill stays reserved for Buy buttons. */
.top { flex-wrap: wrap; row-gap: 6px; padding-bottom: 8px; }
.catnav {
  flex: 1 0 100%; display: flex; gap: 8px; overflow-x: auto; overscroll-behavior-x: contain;
  margin: 0 calc(-1 * var(--gutter)); padding: 2px var(--gutter);
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.catnav::-webkit-scrollbar { display: none; }
/* Phones: the category bar folds away while reading (scroll down) and returns on scroll up or near the top, so the
   sticky header drops from ~117px to the 56px brand row. Keyboard focus inside the bar keeps it open. */
@media (max-width: 719px) {
  /* Owner (Sept 28): solid, never see-through. When the header is on screen it covers from its bottom edge to the very
     top of the iPhone, clock and battery included: it overshoots the top by 40px (off-screen in a browser, under the
     status bar in the home-screen app) so no mode leaves a gap. When it slides away, nothing stays behind. */
  .top { background: var(--ink-950); backdrop-filter: none; -webkit-backdrop-filter: none; }
  /* With the script running, the header is fixed and the page keeps a constant top padding, so folding or hiding the
     header never shifts the content under a reader's thumb (the sticky version jumped the page 62px, Sept 27). */
  html.fixhead .top { position: fixed; left: 0; right: 0; top: -40px; padding-top: calc(50px + env(safe-area-inset-top, 0px)); }
  html.fixhead body { padding-top: var(--top-h, 118px); }
  /* Scroll down and the header and Buy bar slide away; scroll up (or reach the top) and they come back. Keyboard focus
     inside the header keeps it on screen. */
  html.fixhead .top { transition: transform var(--dur-2) var(--ease-out); }
  html.fixhead.scrolling-down .top:not(:focus-within) { transform: translateY(-100%); }
  /* Closing the Browse drawer hands focus back to its trigger in the header. That is not someone tabbing through the
     header, so it must not pin the header open: where :has() works, only visible (keyboard) focus keeps it on screen. */
  @supports selector(:has(a)) { html.fixhead.scrolling-down .top:not(:has(:focus-visible)) { transform: translateY(-100%); } }
  html.scrolling-down .buybar.show { transform: translateY(110%); }
  @media (prefers-reduced-motion: reduce) { html.fixhead .top { transition: none; } }
  /* Our own browsers only: the marker takes the end of the header (a row of its own on most phones), so the first row is
     the name and the trigger, as visitors see it. */
  .internal-chip { order: 2; }
}
.catnav:empty { display: none; }
.catnav a {
  flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 40px; padding: 0 16px;
  border-radius: var(--r-pill); text-decoration: none; white-space: nowrap;
  font: 600 var(--fs-sm)/1 var(--font-ui); color: var(--text-2);
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
  -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-1) ease, box-shadow var(--dur-1) ease, transform 200ms var(--ease-out);
}
.catnav a:active { transform: scale(0.97); transition-duration: 100ms; }
.catnav a[aria-current] { color: var(--text); box-shadow: inset 0 0 0 1.5px var(--accent); }
.catnav a:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .catnav a:hover { color: var(--text); } }

/* Jumps land below the sticky header instead of under it (the wheels; without scripts, the trigger's two targets). */
.shelf, #shelves, .catgrid { scroll-margin-top: var(--nav-h, 120px); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

/* Back to all picks: Pinterest visitors land on a product page with no history, so the way back is explicit. */
.backlink {
  justify-self: start; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; margin: -8px 0 -4px;
  font: 600 var(--fs-sm)/1 var(--font-ui); color: var(--text-2); text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.backlink:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 3px; border-radius: 6px; }
@media (hover: hover) and (pointer: fine) { .backlink:hover { color: var(--text); } }
@media (min-width: 720px) { .backlink { grid-column: 1 / -1; } }

/* Hero */
.hero { padding: var(--sp-5) var(--gutter) var(--sp-6); display: grid; gap: var(--sp-4); }
.hero-media {
  position: relative; border-radius: var(--r-lg); overflow: hidden;
  aspect-ratio: 4 / 5; max-width: 100%; background: var(--ink-800);
  box-shadow: var(--glow-ember);
}
.hero-media img { width: 100%; height: 100%; object-fit: cover; }
/* One restrained Apple-style touch: the hero photo eases back very slightly as you scroll away. Off without support or with reduced motion. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-media img { animation: hero-drift linear both; animation-timeline: scroll(root); animation-range: 0 60vh; transform-origin: 50% 40%; }
  }
}
@keyframes hero-drift { from { transform: scale(1.04); } to { transform: scale(1); } }
.hero-media .tint { position: absolute; inset: 0; background: radial-gradient(80% 60% at 50% 25%, var(--tint, #4a3728), var(--ink-800) 75%); }
.hero-media .chip { position: absolute; top: 14px; left: 14px; background: color-mix(in srgb, var(--ink-950) 70%, transparent); backdrop-filter: blur(8px); }
.hero h1 { font-size: var(--fs-2xl); }
.hero .why { font-family: var(--font-display); font-style: italic; font-variation-settings: "opsz" 24, "SOFT" 40; font-size: 1.25rem; line-height: 1.35; color: var(--text); margin: 0; text-wrap: pretty; }
.hero .checked { font-size: var(--fs-sm); color: var(--text-3); margin: 0; }
.hero .checked a { color: var(--text-2); }
.hero .actions { display: grid; gap: var(--sp-2); }
.hero .slots { display: flex; gap: var(--sp-2); min-height: 0; }
.hero .slots:empty { display: none; }

/* "Why we picked it": folded by default, one tap to open. Keeps the surface to picture, line, button. */
.more { border-top: 1px solid var(--line); padding-top: var(--sp-2); }
.more summary { cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; min-height: 44px; font: 600 var(--fs-sm)/1 var(--font-ui); color: var(--text-2); letter-spacing: .02em; }
.more summary::-webkit-details-marker { display: none; }
.more summary::after { content: ""; width: 9px; height: 9px; border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3); transform: rotate(45deg); transition: transform var(--dur-1) var(--ease-out); margin-right: 4px; }
.more[open] summary::after { transform: rotate(-135deg); }
.more[open] summary { color: var(--text); }
.more .detail, .sheet-inner .detail { display: grid; gap: 10px; color: var(--text-2); margin: 0 0 var(--sp-2); }
.detail p { margin: 0; }
.detail .reason { color: var(--text); }
.detail .highlights { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.detail .highlights li { position: relative; padding-left: 22px; line-height: 1.4; }
.detail .highlights li::before { content: ""; position: absolute; left: 2px; top: .5em; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent); }
.detail .skip { font-size: var(--fs-sm); color: var(--text-3); padding-top: 2px; }
.more .checked { margin: 0 0 var(--sp-2); }
.more .sheet-more { text-align: left; }
summary:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 3px; border-radius: 6px; }

/* Disclosure sits right under the first affiliate button */
.disclosure { margin: 0 var(--gutter); }

/* Product pages: the same in-use photo the Pin shows, so a Pinterest visitor sees what they tapped */
.inuse { margin: var(--sp-5) var(--gutter) 0; max-width: 520px; display: grid; gap: var(--sp-2); }
.inuse img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; border-radius: var(--r-lg); background: var(--ink-800); }
.inuse figcaption { font-size: var(--fs-sm); color: var(--text-3); }

/* Category wheels: three pictures always fully on screen (never cut at the edge), the middle one active and lit,
   the side ones smaller and turned slightly inward like a wheel. The strip moves by one picture per turn:
   translate = --k pictures of (width + gap), where a picture is (100% - 2 gaps) / 3 of the wheel. */
.shelf { padding-top: var(--sp-6); display: grid; gap: var(--sp-2); }
.shelf-head { display: flex; align-items: center; justify-content: space-between; padding: 0 var(--gutter); gap: var(--sp-3); }
.shelf-head h2 { font-size: var(--fs-xl); }
.wheel-ctrls { display: flex; align-items: center; gap: 2px; flex: none; }
.wheel-ctrls[hidden] { display: none; }
.wheel-btn {
  width: 44px; height: 44px; border: 0; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: var(--text); background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
  -webkit-tap-highlight-color: transparent; transition: transform 160ms var(--ease-out), box-shadow 160ms ease;
}
.wheel-btn svg { width: 18px; height: 18px; }
.wheel-btn:active { transform: scale(.94); transition-duration: 80ms; }
.wheel-btn:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .wheel-btn:hover { box-shadow: inset 0 0 0 1.5px var(--accent); } }
.wheel-count { min-width: 3.4em; text-align: center; font: 600 var(--fs-sm)/1 var(--font-ui); color: var(--text-3); font-variant-numeric: tabular-nums; }

.wheel { --gap: 12px; position: relative; overflow: hidden; margin: 0 var(--gutter); padding: 14px 0 12px; touch-action: pan-y; }
.wheel-strip { display: flex; gap: var(--gap); width: 100%; }
.wheel.loop .wheel-strip { transform: translateX(calc((100% + var(--gap)) / -3 * var(--k, 0))); transition: transform 420ms var(--ease-out); }
/* The first-view spin: the whole category flies past once and settles with the brand's slot overshoot. */
.wheel.loop .wheel-strip.spinning { transition-duration: 950ms; transition-timing-function: var(--ease-settle); }
.wheel:not(.loop) .wheel-strip { justify-content: center; }
.wheel.no-anim .wheel-strip, .wheel.no-anim .wheel-item { transition: none !important; }
.wheel-item {
  flex: 0 0 calc((100% - 2 * var(--gap)) / 3); position: relative; padding: 0; border: 0; background: var(--card);
  border-radius: var(--r-md); overflow: hidden; cursor: pointer; -webkit-tap-highlight-color: transparent;
  opacity: .55; transform: perspective(900px) rotateY(0deg) scale(.88);
  transition: transform 420ms var(--ease-out), opacity 420ms var(--ease-out), box-shadow 420ms var(--ease-out);
}
/* Same function list in every state (so each picture glides between states); outer edges turn away, like a drum. */
.wheel-item.left { transform: perspective(900px) rotateY(-14deg) scale(.88); }
.wheel-item.right { transform: perspective(900px) rotateY(14deg) scale(.88); }
.wheel-item.active { opacity: 1; transform: perspective(900px) rotateY(0deg) scale(1); box-shadow: 0 0 0 2px var(--accent), var(--glow-ember); }
.wheel-item .card-media { position: relative; }
/* A mouse drag turns the wheel like a swipe, so the pictures must not start a browser image drag. */
.wheel-item .card-media img { width: 100%; height: 100%; object-fit: cover; display: block; -webkit-user-drag: none; user-select: none; }
/* The wheels are built by script. Holding their space keeps the footer below the fold on tall screens, so nothing jumps. */
#shelves:empty { min-height: 60vh; }
.wheel-item .card-media .tint { position: absolute; inset: 0; background: radial-gradient(80% 60% at 50% 25%, var(--tint, #4a3728), var(--ink-800) 75%); }
.wheel-item:active .card-media { opacity: .85; }
.wheel-item:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: -3px; }
/* Waiting below the fold: pictures hidden until the wheel's first spin. */
@media (prefers-reduced-motion: no-preference) {
  .wheel.armed .wheel-item { opacity: 0; }
}

/* The middle pick, described under the wheel. Fixed line counts so turning never moves the page below. */
.wheel-info { margin: var(--sp-2) var(--gutter) 0; display: grid; gap: 8px; justify-items: start; }
.wheel-info .h3 { font-size: 1.15rem; line-height: 1.25; min-height: 2.5em; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.wheel-info .why { font-family: var(--font-display); font-style: italic; font-variation-settings: "opsz" 18, "SOFT" 40; font-size: 0.98rem; line-height: 1.35; color: var(--text-2); margin: 0; min-height: 2.7em; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.wheel-actions { display: grid; grid-template-columns: 1fr auto; gap: var(--sp-2); width: 100%; margin-top: 2px; }
.wheel-actions a[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.chip-here { color: var(--text); box-shadow: inset 0 0 0 1.5px var(--accent); }
@media (prefers-reduced-motion: no-preference) {
  .wheel-info.swap > * { animation: wheel-in 240ms var(--ease-out) both; }
  .wheel-info.swap > :nth-child(2) { animation-delay: 30ms; }
  .wheel-info.swap > :nth-child(n+3) { animation-delay: 60ms; }
}
@keyframes wheel-in { from { opacity: 0; transform: translateY(6px); } }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.more summary { -webkit-tap-highlight-color: transparent; }
.sheet-more { font-size: var(--fs-xs); color: var(--text-3); text-align: center; margin: 0; }
.sheet-more a { color: var(--text-2); }
.chip-example { color: var(--sage); }

/* Sticky buy bar: hidden until the hero button leaves the screen */
.buybar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex; justify-content: center;
  padding: 6px var(--gutter) calc(8px + env(safe-area-inset-bottom, 0px));
  transform: translateY(110%); transition: transform 240ms var(--ease-out);
  pointer-events: none;
}
.buybar:not(.show) { transition-duration: 180ms; }
.buybar.show { transform: none; pointer-events: auto; }
.buybar .inner {
  width: 100%; max-width: 720px;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 8px 8px 8px 16px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink-900) 85%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--glow-ember);
}
.buybar .name { flex: 1; min-width: 0; font-family: var(--font-display); font-size: var(--fs-md); line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Detail sheet (native dialog) */
dialog.sheet {
  border: 0; padding: 0; margin: 0; width: 100%; max-width: 100%; max-height: 100dvh;
  position: fixed; inset: auto 0 0 0;
  background: transparent; color: var(--text);
}
dialog.sheet::backdrop { background: rgba(10, 7, 5, 0.6); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.sheet-inner {
  max-width: 760px; margin: 0 auto; max-height: 88dvh; overflow: auto; overscroll-behavior: contain;
  background: var(--ink-900); border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding: 8px var(--gutter) calc(20px + env(safe-area-inset-bottom, 0px));
  /* max-content rows: when the sheet is taller than the screen, auto rows shrink to their minimum, and the photo
     (overflow hidden, so its minimum is 0) spilled over the name and text below it. Now every row keeps its full height
     and the sheet scrolls instead. Caught by 01_WORKSPACE/tools/storefront_mobile_check.mjs on a 375 px phone. */
  display: grid; grid-auto-rows: max-content; gap: var(--sp-4);
  box-shadow: 0 -20px 60px -20px rgba(0,0,0,.8), inset 0 1px 0 var(--line-strong);
}
/* The grip is a real drag handle (drag down to close); the padding gives it a finger-sized target. */
.sheet-inner .grip { width: 44px; height: 5px; border-radius: 3px; background: var(--line-strong); margin: 0 auto; padding: 0; box-sizing: content-box; border: 12px solid transparent; background-clip: padding-box; touch-action: none; cursor: grab; }
.sheet-media { border-radius: var(--r-md); overflow: hidden; aspect-ratio: 4 / 3; background: var(--ink-800); position: relative; }
.sheet-media img { width: 100%; height: 100%; object-fit: cover; }
.sheet-media .tint { position: absolute; inset: 0; background: radial-gradient(80% 60% at 50% 25%, var(--tint, #4a3728), var(--ink-800) 75%); }
.sheet-inner .chip { justify-self: start; } /* hug the label, as under the wheels, instead of stretching the width */
.sheet-inner h2 { font-size: var(--fs-xl); }
#sheet-title:focus { outline: none; } /* focused only to anchor the sheet at the top; the buttons keep their focus ring */
.sheet-inner .why { font-family: var(--font-display); font-style: italic; font-variation-settings: "opsz" 24, "SOFT" 40; font-size: 1.15rem; line-height: 1.35; margin: 0; }
.sheet-inner .detail { color: var(--text-2); margin: 0; }
.sheet-inner .actions { display: grid; gap: var(--sp-2); }
.sheet-inner .close { justify-self: end; }
/* The sheet comes from the bottom edge and goes back there; the panel stays solid, only the backdrop fades. */
@media (prefers-reduced-motion: no-preference) {
  /* The slide-up runs from the script (Web Animations) since iPhone Safari sometimes never started the CSS version on a
     freshly opened dialog, leaving the panel parked below the screen until the next scroll (owner, Sept 27). */
  dialog.sheet[open]::backdrop { animation: fade-in 300ms var(--ease-out) both; }
  dialog.sheet.closing .sheet-inner { animation: sheet-down 240ms var(--ease-drawer) both; }
  dialog.sheet.closing::backdrop { animation: fade-out 200ms ease-out both; }
}
@media (prefers-reduced-motion: reduce) { dialog.sheet[open] .sheet-inner { animation: fade-in 150ms ease-out both; } }
/* While the sheet is open the page behind it must not scroll: on phones a finger on the sheet otherwise moved the page. */
html.sheet-open, html.sheet-open body { overflow: hidden; overscroll-behavior: none; }
@keyframes sheet-down { from { transform: none; } to { transform: translateY(100%); } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }

/* "Why we picked it" opens smoothly where the browser supports it; it sits below the Buy button, so it never moves it. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }
  @media (prefers-reduced-motion: no-preference) {
    details.more::details-content { height: 0; overflow: clip; transition: height 240ms var(--ease-out), content-visibility 240ms allow-discrete; }
    details.more[open]::details-content { height: auto; }
  }
}

/* Touch devices: a lighter blur on the Buy bar for smoother scrolling. The phone header is solid with no blur at all
   (owner, Sept 28: when it slides back in, nothing shows through it), so it is left out here; tablets keep the base blur. */
@media (pointer: coarse) {
  .buybar .inner { backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
}

/* Reduced motion: the buy bar fades in place instead of sliding; press feedback stays. */
@media (prefers-reduced-motion: reduce) {
  .buybar { transform: none; opacity: 0; transition: opacity 200ms ease-out !important; }
  .buybar.show { opacity: 1; }
}

/* Footer */
footer { padding: var(--sp-7) var(--gutter) 0; display: grid; gap: var(--sp-2); color: var(--text-3); font-size: var(--fs-xs); }
footer nav { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
footer a { color: var(--text-2); text-decoration: none; }

/* Touch screens: every tap target is at least 44px tall (Apple's minimum); mouse users keep the tighter sizes. */
@media (pointer: coarse) {
  .btn-sm, .catnav a, .top .brand { min-height: 44px; }
  footer a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; }
}

/* Home intro: one line that says what the shop is (a review on Sept 24 read the home page as a demo). */
.intro { margin: var(--sp-4) var(--gutter) 0; font-family: var(--font-display); font-style: italic; font-variation-settings: "opsz" 24, "SOFT" 40; font-size: 1.05rem; line-height: 1.4; color: var(--text-2); text-wrap: pretty; max-width: 40em; }

/* Plain picks lists: what the build writes into each category before the wheels take over. Crawlers and no-script
   visitors read these; with JavaScript they are replaced within a frame, so they never show. */
.shelf.static .picks { list-style: none; margin: 0; padding: 0 var(--gutter); display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--sp-3); }
.shelf.static .picks a { display: grid; gap: 6px; text-decoration: none; color: var(--text); }
.shelf.static .card-media { display: block; border-radius: var(--r-md); overflow: hidden; background: var(--ink-800); }
.shelf.static .card-media img { width: 100%; height: 100%; object-fit: cover; }
.shelf.static b { font: 600 var(--fs-sm)/1.25 var(--font-ui); }
.shelf.static .picks a > span:last-child { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.4; }

/* Preview banner (only when showing sample data) */
.preview-note { margin: 0 var(--gutter); padding: 8px 12px; border-radius: var(--r-sm); background: color-mix(in srgb, var(--sage) 14%, transparent); color: var(--sage); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }

@media (min-width: 720px) {
  .hero { grid-template-columns: 1fr 1fr; align-items: center; gap: var(--sp-6); padding-top: var(--sp-7); }
  .hero-media { aspect-ratio: 4 / 5; }
  .hero-text { display: grid; gap: var(--sp-4); }
  .hero-text .chip { justify-self: start; }
  .wheel { --gap: 18px; }
  .wheel-info { max-width: 560px; }
}

/* Product pages: the notes sit open under the product (owner, Sept 24: "why we chose it ... sizing, what attachments
   fit"), with a small facts grid. The home page keeps the featured pick's notes folded. */
.specs { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 0; padding: 12px 14px; border-radius: var(--r-sm); background: color-mix(in srgb, var(--surface) 80%, transparent); box-shadow: inset 0 0 0 1px var(--line); font-size: var(--fs-sm); }
.specs dt { font: 700 var(--fs-xs)/1.6 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); }
.specs dd { margin: 0; color: var(--text); line-height: 1.5; }
.is-product .more summary { color: var(--text); }
/* The product at the top of a product page is the one tapped on Pinterest, not a featured hero. */
.chip-pin { color: var(--text); box-shadow: inset 0 0 0 1.5px var(--accent); }

/* All picks: product pages end with every category in one grid, so the whole shop is one tap from any Pin. */
.catgrid { padding: var(--sp-7) var(--gutter) 0; display: grid; gap: var(--sp-4); }
.catgrid h2 { font-size: var(--fs-xl); }
.catgrid .tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--sp-3); }
.tile { display: grid; gap: 8px; align-content: start; text-decoration: none; color: var(--text); -webkit-tap-highlight-color: transparent; }
.tile .card-media { border-radius: var(--r-md); overflow: hidden; background: var(--ink-800); transition: box-shadow 200ms var(--ease-out), transform 200ms var(--ease-out); }
.tile .card-media img { width: 100%; height: 100%; object-fit: cover; }
.tile b { font: 600 var(--fs-md)/1.2 var(--font-ui); }
.tile span { font-size: var(--fs-xs); color: var(--text-3); }
.tile:active .card-media { transform: scale(.98); }
.tile:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 3px; border-radius: var(--r-md); }
.tile[aria-current] .card-media { box-shadow: 0 0 0 2px var(--accent); }
@media (hover: hover) and (pointer: fine) { .tile:hover .card-media { box-shadow: 0 0 0 2px var(--accent), var(--glow-ember); } }
.catgrid .all { justify-self: start; }

/* Three sizes (owner, Sept 24). Phone is the default above: the category bar swipes sideways. Tablet (720px and up):
   a wider page and every category chip in view, nothing to swipe. Desktop (1080px and up): the page uses the screen,
   the categories sit in the header row beside the brand, the product photo and text share the width, and each wheel's
   description sits beside it instead of underneath. */
@media (min-width: 720px) {
  :root { --gutter: 28px; }
  .page { max-width: 1040px; }
  .catnav { flex-wrap: wrap; overflow: visible; margin: 0; padding: 0; }
}
@media (min-width: 960px) {
  .shelf { grid-template-columns: minmax(0, 1fr) minmax(280px, 380px); column-gap: var(--sp-6); align-items: center; padding-right: var(--gutter); }
  .shelf-head { grid-column: 1 / -1; padding-right: 0; }
  .shelf .wheel { margin-right: 0; }
  .wheel-info { margin: 0; max-width: none; }
  .catgrid .tiles { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
}
@media (min-width: 1080px) {
  :root { --gutter: 40px; }
  .page { max-width: 1360px; }
  .top { flex-wrap: nowrap; padding-bottom: 10px; }
  .top .spacer { flex: 0 0 var(--sp-5); }
  .catnav { flex: 1 1 auto; justify-content: flex-end; row-gap: 6px; }
  .hero { grid-template-columns: minmax(0, 560px) minmax(0, 1fr); gap: var(--sp-8); padding-top: var(--sp-8); }
  .hero h1 { font-size: clamp(2.4rem, 3.2vw, 3.2rem); }
  .inuse { max-width: 420px; }
  .shelf { grid-template-columns: minmax(0, 1fr) minmax(320px, 420px); }
  .buybar .inner { max-width: 840px; }
}

/* Guides row on the home page (text tiles; the guides have no photos yet) and the two-link nav on text pages. */
.guides-row { margin: var(--sp-6) var(--gutter) 0; display: grid; gap: var(--sp-3); }
.guide-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--sp-3); }
.guide-tile { display: grid; gap: 6px; align-content: start; min-height: 96px; padding: var(--sp-4); border-radius: var(--r-md); background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); text-decoration: none; color: var(--text); transition: box-shadow 200ms var(--ease-out); }
.guide-tile b { font: 600 var(--fs-md)/1.25 var(--font-display); }
.guide-tile span { font-size: var(--fs-xs); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-3); }
.guide-tile:hover { box-shadow: inset 0 0 0 1.5px var(--accent); }
.guide-tile:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }

/* Site nav: Shop, Buying Guides and Deals on every page, in the header after the brand (tablet and up; on phones the
   same three links lead the Menu drawer, since they do not fit beside the name). The outline marks the reader's section. */
.sitenav { display: flex; gap: 4px; }
.sitenav a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px; border-radius: var(--r-pill); color: var(--text-2); text-decoration: none; white-space: nowrap; font: 600 var(--fs-sm) var(--font-ui); -webkit-tap-highlight-color: transparent; }
.sitenav a[aria-current] { color: var(--text); box-shadow: inset 0 0 0 1.5px var(--accent); }
.sitenav a:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .sitenav a:hover { color: var(--text); background: var(--surface); } }
/* Featured picks on the home page: the owner's short list from site.config.json, as product tiles. */
.row-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }
.row-note { font-size: var(--fs-xs); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-3); }
.featured { margin: var(--sp-6) var(--gutter) 0; display: grid; gap: var(--sp-3); }
.featured .tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--sp-3); }
.featured .tile .card-media { aspect-ratio: 4 / 5; }
@media (min-width: 720px) { .featured .tiles { grid-template-columns: repeat(4, 1fr); } }

/* Portafilter size finder (templates/partials/portafilter-tool.html), dropped into markdown pages by {{PORTAFILTER_TOOL}}. */
.pf-tool { display: grid; gap: var(--sp-3); padding: var(--sp-5) var(--sp-4); border-radius: var(--r-md); background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
.pf-tool .pf-sub, .pf-tool .pf-hint, .pf-tool .pf-foot, .pf-tool .pf-none, .pf-tool .pf-who { margin: 0; }
.pf-tool .pf-sub { color: var(--text-2); }
.pf-tool .pf-hint, .pf-tool .pf-foot { font-size: var(--fs-sm); color: var(--text-3); }
.pf-tool .pf-foot { padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.pf-tool .pf-label { font: 600 var(--fs-sm)/1.3 var(--font-ui); color: var(--text); }
.pf-tool .pf-input { width: 100%; min-height: 48px; padding: 10px 14px; font: 400 var(--fs-md)/1.3 var(--font-ui); color: var(--text); background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-sm); -webkit-appearance: none; appearance: none; }
.pf-tool .pf-input:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
.pf-tool .pf-results { display: grid; gap: var(--sp-2); }
.pf-tool .pf-row { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); width: 100%; min-height: 48px; padding: 10px 14px; font: inherit; color: var(--text); text-align: left; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer; }
.pf-tool .pf-row:hover, .pf-tool .pf-row:focus-visible { border-color: var(--accent); outline: none; }
.pf-tool .pf-name { font-weight: 600; font-size: var(--fs-sm); }
.pf-tool .pf-brand { display: block; margin-top: 2px; font-weight: 400; font-size: var(--fs-xs); color: var(--text-3); }
.pf-tool .pf-size { font: 700 var(--fs-md)/1 var(--font-display); color: var(--accent); white-space: nowrap; }
.pf-tool .pf-card { display: grid; gap: var(--sp-3); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.pf-tool .pf-card h3 { margin: 0; }
.pf-tool .pf-big { font: 600 var(--fs-3xl)/1 var(--font-display); color: var(--accent); }
.pf-tool .pf-who { font-size: var(--fs-sm); color: var(--text-3); }
.pf-tool .pf-k { margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--text); }
.pf-tool .pf-list { margin: 0; padding-left: 1.2em; display: grid; gap: 4px; font-size: var(--fs-sm); color: var(--text-2); }
.pf-tool .pf-flag { margin: var(--sp-1) 0 0; padding: var(--sp-3) var(--sp-4); background: color-mix(in srgb, var(--clay) 12%, var(--card)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--clay) 30%, transparent); border-radius: var(--r-sm); color: var(--blush); font-size: var(--fs-sm); }
.pf-tool .pf-flag strong { color: var(--text); }
.pf-tool .pf-back { justify-self: start; min-height: 44px; padding: 0 var(--sp-2); font: 600 var(--fs-sm)/1 var(--font-ui); color: var(--accent-hi); background: none; border: 0; cursor: pointer; text-decoration: underline; }

/* The finder as a page hero ({{PORTAFILTER_TOOL_HERO}}): same tool, more presence. */
.pf-tool.pf-hero { padding: var(--sp-6) var(--sp-5); background: linear-gradient(180deg, var(--card), var(--surface)); box-shadow: inset 0 0 0 1px var(--line-strong), 0 24px 60px -36px rgba(0, 0, 0, 0.8); }
.pf-tool.pf-hero .h2 { font-size: var(--fs-2xl); line-height: var(--lh-tight); }
.pf-tool.pf-hero .h2 { max-width: 16ch; }
.pf-tool.pf-hero .pf-input { min-height: 56px; font-size: var(--fs-lg); }

/* Guides index: one card per guide with an obvious next step. */
.guide-card { display: grid; gap: var(--sp-3); padding: var(--sp-5) var(--sp-4); border-radius: var(--r-md); background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
.guide-card h2 { margin: 0; font-size: var(--fs-xl); }
.guide-card h2 a { color: var(--text); text-decoration: none; }
.guide-card h2 a:hover { color: var(--accent-hi); }
.guide-card p { margin: 0; color: var(--text-2); }
.guide-card .actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.guide-card .actions a { text-decoration: none; }
.pf-tool .pf-pick { display: grid; gap: var(--sp-2); }
.pf-tool select.pf-input { background-image: linear-gradient(45deg, transparent 50%, var(--text-3) 50%), linear-gradient(135deg, var(--text-3) 50%, transparent 50%); background-position: calc(100% - 22px) 55%, calc(100% - 16px) 55%; background-size: 6px 6px; background-repeat: no-repeat; padding-right: 44px; cursor: pointer; }
.pf-tool select.pf-input:disabled { color: var(--text-3); cursor: default; }
.pf-tool .pf-row2 { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.pf-tool .pf-row2 b { color: var(--text); }
.pf-tool .pf-row2 a, .pf-tool .pf-flag a { color: var(--accent-hi); }
@media (min-width: 720px) { .pf-tool .pf-pick { grid-template-columns: 1fr 1fr; } }

/* "Before you buy" on product pages: three checks, then who it fits and who it does not. */
.checks { display: grid; gap: var(--sp-2); margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.checks h3 { margin: 0; font-size: var(--fs-md); }
.checks ul { margin: 0; padding-left: 1.2em; display: grid; gap: 6px; color: var(--text-2); font-size: var(--fs-sm); }
.checks .fitline { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.checks .fitline b { color: var(--text); font-weight: 600; }

/* Fit funnel (guides): three taps, one pick shown at home, the kit, one Buy button. Display work: the label is the
   question, the answer is a product in a kitchen. Facts come from the product records at build time. */
.ff { display: grid; gap: var(--sp-4); padding: var(--sp-5) var(--sp-4); border-radius: var(--r-md); background: linear-gradient(180deg, var(--card), var(--surface)); box-shadow: inset 0 0 0 1px var(--line-strong); scroll-margin-top: 80px; }
.ff .h2 { margin: 0; font-size: var(--fs-2xl); line-height: var(--lh-tight); max-width: 18ch; }
.ff .ff-sub { margin: 0; color: var(--text-2); }
.ff .ff-qs { display: grid; gap: var(--sp-3); }
.ff .ff-q { margin: 0; padding: 0; border: 0; min-width: 0; display: grid; gap: 8px; }
.ff .ff-label { padding: 0; font: 600 var(--fs-sm)/1.3 var(--font-ui); color: var(--text); }
.ff .ff-opts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.ff .ff-opt { display: grid; gap: 2px; align-content: center; min-height: 56px; padding: 8px 6px; border: 0; border-radius: var(--r-sm); background: var(--card); box-shadow: inset 0 0 0 1px var(--line); color: var(--text-2); font: 600 var(--fs-sm)/1.2 var(--font-ui); text-align: center; cursor: pointer; transition: box-shadow var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }
.ff .ff-opt small { display: block; font: 400 var(--fs-xs)/1.2 var(--font-ui); color: var(--text-3); }
.ff .ff-opt:hover { box-shadow: inset 0 0 0 1px var(--accent); color: var(--text); }
.ff .ff-opt[aria-pressed="true"] { background: color-mix(in srgb, var(--accent) 16%, var(--card)); box-shadow: inset 0 0 0 2px var(--accent); color: var(--text); }
.ff .ff-opt[aria-pressed="true"] small { color: var(--text-2); }
.ff .ff-opt:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }
.ff .ff-results { display: grid; }
.ff .ff-result { display: grid; gap: var(--sp-3); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.ff .ff-photo { margin: 0; border-radius: var(--r-md); overflow: hidden; aspect-ratio: 4 / 3; background: var(--ink-800); }
.ff .ff-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ff .ff-eyebrow { margin: 0; font: 600 var(--fs-xs)/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--accent-hi); }
.ff .ff-name { margin: 0; font-size: var(--fs-xl); line-height: var(--lh-tight); }
.ff .ff-why { margin: 0; font-family: var(--font-display); font-style: italic; font-variation-settings: "opsz" 24, "SOFT" 40; font-size: 1.1rem; line-height: 1.4; color: var(--text); }
.ff .ff-h4 { margin: var(--sp-1) 0 0; font: 600 var(--fs-sm)/1.3 var(--font-ui); color: var(--text-3); letter-spacing: .02em; }
.ff .ff-checks, .ff .ff-kit { margin: 0; padding-left: 1.2em; display: grid; gap: 6px; font-size: var(--fs-sm); color: var(--text-2); }
.ff .ff-kit b { color: var(--text); font-weight: 600; }
.ff .ff-kit a, .ff .ff-flag a { color: var(--accent-hi); }
.ff .ff-flag { margin: 0; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm); background: color-mix(in srgb, var(--clay) 12%, var(--card)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--clay) 30%, transparent); font-size: var(--fs-sm); color: var(--text); }
.ff .ff-sits { display: grid; gap: 6px; margin: 0; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm); background: color-mix(in srgb, var(--clay) 12%, var(--card)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--clay) 30%, transparent); }
.ff .ff-sits p { margin: 0; font-size: var(--fs-sm); color: var(--text); }
.ff .ff-sits .ff-sits-h { font: 600 var(--fs-xs)/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--accent-hi); margin-bottom: 2px; }
.ff .ff-opts-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ff .ff-place { display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1px var(--line-strong); font: 600 var(--fs-xs)/1.6 var(--font-ui); color: var(--text-3); white-space: nowrap; vertical-align: middle; }
.ff .ff-actions { display: grid; gap: var(--sp-2); margin-top: var(--sp-1); }
.ff .ff-foot { margin: 0; padding-top: var(--sp-3); border-top: 1px solid var(--line); font-size: var(--fs-xs); color: var(--text-3); }
@media (min-width: 720px) {
  .ff .ff-result { grid-template-columns: minmax(0, 300px) minmax(0, 1fr); grid-auto-flow: dense; column-gap: var(--sp-5); }
  .ff .ff-result > .ff-photo { grid-column: 1; grid-row: 1 / span 8; }
  .ff .ff-result > :not(.ff-photo) { grid-column: 2; }
  .ff .ff-actions { grid-template-columns: auto auto; justify-content: start; }
}

/* Folded guide sections: the heading is the tap target; the words stay in the page. */
.prose details.fold { margin: 0; border-top: 1px solid var(--line); scroll-margin-top: 80px; }
.prose details.fold > summary { list-style: none; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: 56px; padding: var(--sp-2) 0; cursor: pointer; }
.prose details.fold > summary::-webkit-details-marker { display: none; }
.prose details.fold > summary h2 { margin: 0; font-size: var(--fs-lg); }
.prose details.fold > summary::after { content: "+"; flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--line-strong); color: var(--text-2); font: 500 20px/1 var(--font-ui); transition: transform var(--dur-2) var(--ease-out); }
.prose details.fold[open] > summary::after { transform: rotate(45deg); }
.prose details.fold > summary:hover::after { box-shadow: inset 0 0 0 1px var(--accent); color: var(--text); }
.prose details.fold > summary:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; border-radius: 4px; }
.prose details.fold > :not(summary) { margin-top: var(--sp-3); }
.prose details.fold > :last-child { margin-bottom: var(--sp-4); }
.prose details.fold .pf-tool { margin-top: var(--sp-3); }

/* "Goes with" on product pages (decision 62): the two or three things bought together, each one tap away. */
.kit { display: grid; gap: var(--sp-2); margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.kit h3 { margin: 0; font-size: var(--fs-md); }
.kit ul { margin: 0; padding-left: 1.2em; display: grid; gap: 6px; color: var(--text-2); font-size: var(--fs-sm); }
.kit a { color: var(--text); font-weight: 600; }
.kit a:hover { color: var(--accent-hi); }

/* Deals lane (guides): one card per deal that held a full day; the button is the only loud thing on the card. */
.deals { list-style: none; margin: var(--sp-4) 0; padding: 0; display: grid; gap: var(--sp-3, 16px); }
.deals .deal { border: 1px solid var(--line); border-radius: 16px; padding: var(--sp-4); display: grid; gap: var(--sp-2); }
.deals .deal h3 { margin: 0; font-size: var(--fs-md); }
.deals .deal p { margin: 0; color: var(--text-2); font-size: var(--fs-sm); }
.deals .deal-alt b { color: var(--text); font-weight: 600; }
.deals .deal-cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3, 16px); margin-top: var(--sp-1, 4px); }
.deals .deal-verified { font-size: var(--fs-xs, 0.8rem); color: var(--text-2); }
.deals-empty { border: 1px dashed var(--line); border-radius: 16px; padding: var(--sp-4); margin: var(--sp-4) 0; }
.deals-empty p { margin: 0; color: var(--text-2); }
.deals-empty b { color: var(--text); }

/* Browse (Sept 30, Codex pack section D): one trigger in the header and one drawer, on every page. The category bar stays
   on the store pages (Shop and product pages) at every size it has today, decisions 38 and 42, except on a phone's
   product page, where the Menu trigger stands in for it so the Pin's product and its Buy button fit the first screen.
   Guide and text pages get the drawer instead of a second header row. The drawer is the detail sheet (dialog.sheet: same
   panel, backdrop, slide and easing) holding links. Phones: the trigger reads Menu and the drawer leads with Shop, Buying
   Guides and Deals, which have no room beside the name. From 720px the header shows those three itself, the trigger reads
   Browse, and the drawer is a panel under it holding the categories. */
.browse-btn {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px; border-radius: var(--r-pill);
  font: 600 var(--fs-sm)/1 var(--font-ui); color: var(--text); text-decoration: none; white-space: nowrap;
  box-shadow: inset 0 0 0 1.5px var(--line-strong); -webkit-tap-highlight-color: transparent;
  transition: transform 200ms var(--ease-out), box-shadow var(--dur-1) ease;
}
.browse-btn svg { width: 16px; height: 16px; flex: none; color: var(--accent); }
.browse-btn:active { transform: scale(0.97); transition-duration: 100ms; }
.browse-btn[aria-expanded="true"] { box-shadow: inset 0 0 0 1.5px var(--accent); }
.browse-btn:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .browse-btn:hover { box-shadow: inset 0 0 0 1.5px var(--accent); } }
@media (max-width: 719px) {
  .sitenav, .w-browse { display: none; }
  /* Phone product page (the Pinterest landing): one 63px header row instead of 117px. The categories are in the Menu
     drawer and the "All our picks" tiles. Owner's call (it changes decision 42 on phones): delete this line to bring the
     swipeable bar back here. */
  .top.on-product .catnav { display: none; }
  /* Without scripts the drawer cannot open, so the three links come back as a header row of their own (the footer
     carries them too, for browsers that do not know this query). */
  @media (scripting: none) { .sitenav { display: flex; order: 1; flex: 1 0 100%; } .catnav { order: 2; } }
}
/* The page lock is the detail sheet's (html.sheet-open). On pages whose header is sticky (guides, text pages, tablets and
   up) that lock turns <body> into a scroll box, which un-sticks the header: it vanished behind the dimmed page while the
   drawer was open. clip locks the same way without making a scroll box. The stable gutter keeps a mouse user's page from
   shifting sideways when the scrollbar goes. Both apply only while the drawer is open. */
html.browse-open { scrollbar-gutter: stable; }
@supports (overflow: clip) { html.browse-open body { overflow: clip; } }
/* Up to 40px from the top of the screen (the detail sheet stops at 88dvh): the three rows and twelve chips then fit most
   phones without scrolling inside; on a shorter screen the drawer scrolls, as the detail sheet does. */
.browse .sheet-inner { gap: var(--sp-3); max-height: calc(100dvh - 40px); }
.browse-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
#browse-title:focus { outline: none; } /* focused only to start the drawer at its top, like #sheet-title */
/* The three destinations: serif rows on hairlines, the ember dot on the reader's section. */
.browse-site { display: grid; border-top: 1px solid var(--line); }
.browse-site a {
  display: flex; align-items: center; gap: 10px; min-height: 48px; border-bottom: 1px solid var(--line);
  font: 500 var(--fs-lg)/var(--lh-snug) var(--font-display); letter-spacing: -0.015em; font-variation-settings: "opsz" 24, "SOFT" 30;
  color: var(--text); text-decoration: none; -webkit-tap-highlight-color: transparent; transition: color var(--dur-1) ease;
}
.browse-site a[aria-current]::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent); }
.browse-site a:active { color: var(--accent-hi); }
.browse .row-note { margin: var(--sp-2) 0 0; }
/* The categories: the bar's chips, two to a row. The ember outline marks a product page's own category, and only that:
   a mouse hover gets its own cue (brighter text, a lighter fill), so the pill under the pointer never reads as "you are here". */
.browse-cats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.browse-cats a {
  display: flex; align-items: center; min-height: 44px; padding: 0 16px; border-radius: var(--r-pill);
  font: 600 var(--fs-sm)/1.2 var(--font-ui); color: var(--text-2); text-decoration: none;
  background: var(--card); box-shadow: inset 0 0 0 1px var(--line); -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-1) ease, background-color var(--dur-1) ease, box-shadow var(--dur-1) ease, transform 200ms var(--ease-out);
}
.browse-cats a:active { transform: scale(0.97); transition-duration: 100ms; }
.browse-cats a[aria-current] { color: var(--text); box-shadow: inset 0 0 0 1.5px var(--accent); }
.browse-site a:focus-visible, .browse-cats a:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }
.browse-site a:focus-visible { border-radius: 6px; }
@media (hover: hover) and (pointer: fine) { .browse-site a:hover { color: var(--accent-hi); } .browse-cats a:hover { color: var(--text); background: var(--ink-700); } }
/* A same-page category jump focuses its wheel (tabindex -1, set by the drawer's script) so Tab carries on from there; like
   #sheet-title, it is focused only as a starting point, so no ring around the whole wheel. */
.shelf[tabindex="-1"]:focus { outline: none; }
/* Tablet and up: no trigger on store pages (every chip is already in view). Elsewhere the drawer is a panel under the
   header, its right edge on the trigger (the drawer's script sets the two offsets): a lighter dim with no blur, no grip,
   and a short fade with a small drop instead of the phone's slide. */
@media (min-width: 720px) {
  .w-menu, .top.has-bar .browse-btn, .browse-site, .browse .grip, .browse .row-note { display: none; }
  dialog.sheet.browse { inset: var(--browse-top, 72px) var(--browse-right, var(--gutter)) auto auto; width: min(520px, calc(100vw - 2 * var(--gutter))); overflow: visible; }
  dialog.sheet.browse::backdrop { background: rgba(10, 7, 5, 0.35); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .browse .sheet-inner { max-height: calc(100dvh - var(--browse-top, 72px) - var(--sp-5)); padding: var(--sp-4) var(--sp-5) var(--sp-5); border-radius: var(--r-lg); box-shadow: var(--glow-soft), inset 0 0 0 1px var(--line-strong); }
  .browse-cats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  @media (prefers-reduced-motion: no-preference) { dialog.sheet.browse.closing .sheet-inner { animation: fade-out 160ms ease-out both; } }
}
/* Desktop store header (Shop and product pages): the brand, three links and every chip share one row, and the chips wrap
   to a second row when they must, never a third (107px, as today). The three links never shrink. From 1280px the name
   stays on one line. Guide and text pages have no chips, so their name is always on one line. */
@media (min-width: 1080px) { .top:not(.has-bar) .brand, .sitenav, .browse-btn { flex: none; } }
@media (min-width: 1280px) {
  .top.has-bar .brand { flex: none; }
  /* Our own browsers only: the "Internal testing" marker takes header room, so the name may wrap again (as it does today)
     rather than push the chips to a third row. */
  .top.has-bar:has(.internal-chip) .brand { flex: 0 1 auto; }
}
/* 1080 to 1279px (small laptops, Windows laptops at 125-175%, a tablet on its side): the third link costs about one chip
   of room, so here the name breaks onto two lines as it does today (the logo keeps its size: .top .brand svg is
   flex: none), and the header packs a little closer: 8px between its parts, the links 10px in from their edges with no
   gap between them, the chips 4px apart and 12px in. Measured with the real fonts (drawer_check.mjs): two chip rows and
   107px at every width from 1080 to 1279, as today, and still two with the chip and link text widened by 0.8px a letter. */
@media (min-width: 1080px) and (max-width: 1279px) {
  .top.has-bar { column-gap: var(--sp-2); }
  .top.has-bar .spacer { flex-basis: 0; }
  .top.has-bar .sitenav { gap: 0; }
  .top.has-bar .sitenav a { padding: 0 10px; }
  .top.has-bar .catnav { gap: 6px 4px; }
  .top.has-bar .catnav a { padding: 0 12px; }
}
/* Windows High Contrast (forced colors) drops box-shadow, which draws the trigger's and the pills' edges, the current-place
   outlines and the panel's edge, and repaints the ember dot. System-color borders and outlines stand in: ButtonText for an
   edge, Highlight for where the reader is (and for an open trigger). Outlines, not borders, on the header links and the bar's
   chips, so they keep their size as the highlight moves; the focus ring still wins on the focused link. */
@media (forced-colors: active) {
  .browse-btn, .browse-cats a { border: 1px solid ButtonText; }
  .browse-btn[aria-expanded="true"] { border-color: Highlight; }
  .browse-cats a[aria-current] { border: 2px solid Highlight; }
  .sitenav a[aria-current]:not(:focus-visible), .catnav a[aria-current]:not(:focus-visible) { outline: 2px solid Highlight; outline-offset: -2px; }
  .browse-site a[aria-current]::before { forced-color-adjust: none; background: Highlight; }
  .browse .sheet-inner { border-top: 1px solid CanvasText; }
}
@media (forced-colors: active) and (min-width: 720px) { .browse .sheet-inner { border: 1px solid CanvasText; } }
