/* Product page (tea/object).
   Header reuses the shop pink tint; marquee sits above this page's own
   back-arrow row, which is what actually sticks below the header. */

.product__back {
  position: sticky;
  top: 3.625rem; /* below the sticky header, matches .chips on shop.php */
  z-index: 5;
  display: block;
  width: fit-content;
  padding: 0.75rem var(--gutter) 0.75rem calc(var(--gutter) + 1%);
  font-size: 1.875rem; /* 30px — off the token scale, between --text-title (24) and --text-menu (36) */
  /* explicit, not inherited: over a flat page background the
     difference-blend glyph below reads solid and heavier than the same
     weight does over a busy photo — pin one weight so it's consistent
     everywhere this class is reused (product/article/account pages) */
  font-weight: var(--weight-regular);
  line-height: 1;
  text-decoration: none;
  /* white + difference = adapts to whatever scrolls beneath: reads black
     on the paper background, white over dark imagery */
  color: #fff;
  mix-blend-mode: difference;
}

/* phone: half the seam between the arrow row and the photo (the arrow
   keeps its 0.75rem — that's tap-target height, not air) */
@media (max-width: 45.9375rem) {
  .page.product {
    padding-top: 0.375rem;
  }
}

/* ---- image / slider ---- */

.product__media {
  position: relative; /* anchors .product-card__bestseller (shop.css) */
}

/* +20% over shop.css's own bestseller badge size on this page — badge/
   peek/text all scaled together to stay in proportion. Anchor offset
   (right/bottom on .product-card__bestseller) stays as-is — that's
   distance from the card corner, not part of the icon's own scale. */
.product__media .product-card__bestseller {
  width: 6.525rem;    /* 104.4px, 87px * 1.2 */
  height: 5.23125rem; /* 83.7px, 69.75px * 1.2 */
}

.product__media .product-card__bestseller-badge {
  width: 3.375rem; /* 54px, 45px * 1.2 */
  height: 3.375rem;
}

.product__media .product-card__bestseller-peek {
  width: 3.20625rem; /* 51.3px, 42.75px * 1.2 */
  height: 5.23125rem; /* 83.7px, 69.75px * 1.2 */
}

.product__media .product-card__bestseller-text {
  left: 0.225rem;     /* 3.6px, 3px * 1.2 */
  top: 2.86875rem;    /* 45.9px, 38.25px * 1.2 */
  width: 2.925rem;    /* 46.8px, 39px * 1.2 */
  font-size: 0.61875rem; /* 9.9px, 8.25px * 1.2 */
}

.product__image,
.product__slider {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4; /* the shop's uniform photo format, shown whole */
}

.product__image {
  object-fit: cover;
}

.product__image--empty {
  background: #ececec;
}

/* Continuous drift, not a snap-between-photos jump — same engine as
   the marquee (js/scrub-strip.js): two copies of the photo set loop via
   translateX(-50%), draggable/flickable the same way. */
.product__slider {
  position: relative;
  overflow: hidden;
  cursor: grab;
}

.product__slider.is-dragging {
  cursor: grabbing;
}

.product__slider-track {
  display: flex;
  height: 100%;
  touch-action: pan-y; /* horizontal drags are ours, vertical scroll stays native */
  animation: product-slide-scroll 30s linear infinite; /* no-JS fallback pace, ~40px/s for a 3-photo set */
}

/* js/scrub-strip.js splits the track's two photo sets into their own
   .scrub-strip__group wrappers (position set inline by the JS) so they
   can relay past each other independently. */
.product__slider-track .scrub-strip__group {
  display: flex;
  height: 100%;
  touch-action: pan-y;
  width: max-content; /* shrink-to-fit — getBoundingClientRect() must report real content width, not the viewport's */
}

@keyframes product-slide-scroll {
  to { transform: translateX(-50%); }
}

.product__slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- buy box ---- */

.product__buy {
  padding: 1.5rem var(--gutter) 0;
  text-align: center;
}

.product__title {
  font-size: var(--text-title); /* 24px */
  font-weight: var(--weight-medium);
}

.product__subtitle {
  font-size: var(--text-title);
  font-weight: var(--weight-light);
}

.product__price {
  margin-top: 1.5rem;
  font-size: var(--text-title);
}

.product__stock {
  font-size: var(--text-body);
  font-weight: var(--weight-light);
}

.product__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1rem;
}

.product__qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 8.75rem; /* 140px */
  height: 3.3125rem; /* 53px */
  border: var(--border-thin);
  border-radius: var(--radius-l);
  font-size: var(--text-title);
  font-weight: var(--weight-regular);
}

/* button-centering convention (site-wide): flex/grid + place-items/
   justify+align center, plus an explicit line-height so the glyph
   centers on its own box rather than an inherited, taller line box. */
.product__qty-btn {
  background: none;
  border: none;
  padding: 0;
  min-width: 44px; /* tap target */
  min-height: 44px;
  display: grid;
  place-items: center;
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

/* same convention as .product__basket:disabled — dims to the .u-dimmed opacity */
.product__qty-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.product__qty-value {
  flex: 1;
  text-align: center;
  line-height: 1;
}

.product__basket {
  display: grid;
  place-items: center;
  width: 11.6875rem; /* 187px */
  height: 3.3125rem; /* 53px — matches .product__qty's own height */
  border: var(--border-thin);
  border-radius: var(--radius-l);
  /* buttons get a UA-default grey face color unless reset — without
     this, the real <button> (real Shopify variant) and the mailto <a>
     fallback (no variant yet) render with different backgrounds */
  background: none;
  font-size: var(--text-body); /* 20px */
  font-weight: var(--weight-regular);
  line-height: 1;
  text-decoration: none;
  cursor: pointer; /* a <button> defaults to the arrow, unlike the links beside it */
}

/* phones: one row pinned to the content edges, slimmer boxes (44px =
   the tap-target floor) */
@media (max-width: 45.9375rem) {
  .product__title {
    font-size: 1.625rem; /* 26px — Vytas-tuned, between the 24/28 tokens */
  }

  .product__actions {
    flex-wrap: nowrap;
    justify-content: space-between;
  }

  .product__qty {
    width: 7.5rem; /* 120px */
    height: 2.75rem; /* 44px */
    font-size: var(--text-body);
  }

  .product__basket {
    width: 10.25rem; /* 164px */
    height: 2.75rem;
  }
}

/* same pink hover as the shop cards' basket */
.product__basket:not(:disabled):focus-visible {
  background: #ffdff9;
}

@media (hover: hover) {
  .product__basket:not(:disabled):hover {
    background: #ffdff9;
  }
}

/* explicit, not the browser's own inconsistent disabled style — same
   opacity as .u-dimmed (base.css), applied to .product__stock when out
   of stock, so the label and button dim together as one state */
.product__basket:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ---- accordion ---- */

.accordion {
  margin-top: 1.5rem;
}

.accordion__item {
  border-top: var(--border-thin);
  padding: var(--gutter);
}

.accordion__item:last-child {
  border-bottom: var(--border-thin);
}

.accordion__summary {
  cursor: pointer;
  list-style: none;
}

.accordion__summary::-webkit-details-marker {
  display: none;
}

/* h2, not a styled span/div: it's a real section title (same level as
   "Related products"/"Related stories" below it), and it's the sole
   content of <summary> per the heading-content exception in the
   summary content model — spec-valid, unlike nesting a heading a few
   levels deep inside a wrapper span. */
.accordion__label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-title); /* 24px */
  font-weight: var(--weight-medium);
}

.accordion__icon {
  width: auto;
  height: 2.5rem;
}

.accordion__content {
  overflow: hidden; /* clips mid-animation (accordion.js animates height) */
  font-size: var(--text-body);
  font-weight: var(--weight-light);
  line-height: 1.4;
}

.accordion__item[open] .accordion__content {
  margin-top: 1rem;
}

.accordion__content :is(p, dl, ul) + :is(p, dl, ul) {
  margin-top: 1em;
}

/* Optional video above the Description text — sized to the accordion's
   own container width, not full-bleed like the journal article's video
   block (article.css uses the same aspect-ratio-on-iframe technique). */
.product__video {
  margin-bottom: 1em;
}

.product__video iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
}

.product__prepare div + div {
  margin-top: 1em;
}

.product__prepare dt {
  font-weight: var(--weight-semibold);
}

/* ---- +/- toggle: two bars inside a circle, CSS-only animated ----
   Lives outside <summary> (accordion.js wires its click) so it can sit
   after .accordion__content in the markup — after the text once a
   section is open, right below the heading when it's collapsed (no
   content in the way), matching the design in both states. */

.accordion__toggle {
  position: relative;
  display: block;
  width: 2.625rem; /* 42px */
  height: 2.625rem;
  margin: 1rem auto 0;
  border: var(--border-thick);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.accordion__toggle-h,
.accordion__toggle-v {
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--color-ink);
  transition: transform 0.2s ease;
}

.accordion__toggle-h {
  width: 1.25rem;
  height: 2px;
  transform: translate(-50%, -50%);
}

.accordion__toggle-v {
  width: 2px;
  height: 1.25rem;
  transform: translate(-50%, -50%);
}

.accordion__item[open] .accordion__toggle-v {
  transform: translate(-50%, -50%) scaleY(0);
}

/* ---- related products / stories ---- */

.product__section-title {
  margin-top: 2.5rem;
  padding-inline: var(--gutter);
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  text-align: center;
}

.product .products {
  margin-top: 1.5rem; /* more air below "Related products" than .products' shared base */
  /* no padding-inline here: .page (parent) already applies the gutter */
}

/* Same 1-big/2-small rhythm and grid technique as journal.css's
   .articles/.article-card: a plain 2-col grid (not a flex stack) so a
   lone story can go full-width via grid-column while a pair sits side
   by side, with no DOM restructuring needed either way. */
.stories {
  list-style: none;
  margin: 1.5rem 0 0; /* more air below "Related stories" */
  padding: 0; /* .page (parent) already applies the gutter */
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 1.4375rem; /* 23px, matches .products/.articles */
  row-gap: 2.5rem;
}

.story-card--featured {
  grid-column: 1 / -1;
}

/* flex column filling the grid cell's stretched height so
   .story-card__more's auto top-margin can push it to the bottom —
   same technique as .article-card */
.story-card {
  position: relative;
  display: flex;
  flex-direction: column;
  text-align: center;
}

.story-card__link {
  position: relative;
  display: block;
  text-decoration: none;
}

.story-card__img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.story-card__img--empty {
  background: #ececec;
}

.story-card__title {
  display: block;
  margin-top: 0.75rem;
  font-weight: var(--weight-regular);
  text-align: left;
  /* journal's title is a real <h2> and inherits base.css's h1-h4
     line-height (1.15); this is a plain span, so it needs it explicit
     to actually match rather than falling back to body's 1.4 */
  line-height: 1.15;
}

.story-card__excerpt {
  margin-top: 0.75rem;
  margin-bottom: 1rem; /* floor gap before Read, on top of its own auto push */
  text-align: left;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.story-card__more {
  position: relative;
  z-index: 2;
  align-self: center; /* .story-card's default stretch (needed for img/title/excerpt) would otherwise force this to full card width */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: auto; /* pushes to the bottom of the grid-stretched card */
  padding: 0.25em 1em;
  border: var(--border-thin);
  border-radius: var(--radius-l);
  font-weight: var(--weight-regular);
  line-height: 1;
  text-decoration: none;
}

.story-card__more:focus-visible {
  background: #fdff90; /* the Journal pill's yellow */
}

@media (hover: hover) {
  .story-card__more:hover {
    background: #fdff90;
  }
}

.story-card--featured .story-card__title {
  font-size: var(--text-title); /* 24px */
  font-weight: var(--weight-medium);
}

.story-card--featured .story-card__excerpt {
  font-size: 1.125rem; /* 18px — deliberate exception to the token scale; nearest tokens are --text-ui (16px) and --text-body (20px) */
  font-weight: var(--weight-regular);
  -webkit-line-clamp: 4;
}

.story-card--featured .story-card__more {
  font-size: var(--text-body); /* 20px */
}

.story-card:not(.story-card--featured) .story-card__title {
  font-size: var(--text-body); /* 20px */
  /* reserves 2 lines regardless of actual title length, so the excerpt
     below always starts at the same Y between two cards in a row */
  min-height: 2.875rem;
}

/* tablet band: the cards run wide enough that titles fit one line, so
   the two-line reservation only shows as a blank line before the excerpt */
@media (min-width: 46rem) and (max-width: 71.9375rem) {
  /* Title + typology read ABOVE the photo: the buy box dissolves
     (display: contents) so its children join the page column, and the
     two are ordered up past the media. The box's centering/padding die
     with it — restated on the children; price's own 1.5rem top margin
     carries the old box padding. */
  .page.product {
    display: flex;
    flex-direction: column;
  }

  .product__buy {
    display: contents;
  }

  .product__title {
    order: -2;
    font-size: var(--text-subheading); /* 28px, the 24px base +4 */
  }

  .product__subtitle {
    order: -1;
    margin-bottom: 1rem; /* air before the photo */
  }

  .product__title,
  .product__subtitle,
  .product__price,
  .product__stock {
    text-align: center;
  }

  .story-card:not(.story-card--featured) .story-card__title {
    min-height: 0;
  }

  /* bestseller badge up 40% on the product page's main photo and on
     related-products cards (same tablet-dust reasoning as the listings) */
  .product__media .product-card__bestseller,
  .related-pair .product-card__bestseller {
    scale: 1.4;
    transform-origin: bottom right;
  }
}

.story-card:not(.story-card--featured) .story-card__excerpt {
  font-size: var(--text-small); /* 14px */
  -webkit-line-clamp: 3;
}

.story-card:not(.story-card--featured) .story-card__more {
  font-size: var(--text-ui); /* 16px */
}

/* Contiguous full-width slides: overlap each by 1px — at fractional
   viewport widths the rounded image edges otherwise leave a hairline of
   background between slides, seen as a flickering vertical line. */
.product__slide,
.product-card__slide,
.article__gallery-slide {
  margin-right: -1px;
}

/* object-fit:cover can leave a sub-pixel unpainted column at an image's
   edge at fractional geometry — while the track's composited layer moves
   it blinks as a white vertical line against dark imagery (invisible at
   higher zoom, where device pixels are finer). A ~0.4% scale overdraws
   the box edges without touching layout; the surrounding overflow:hidden
   viewports clip the excess. */
.product__slide,
.product-card__slide,
.article__gallery-slide,
.home-shop__img {
  transform: scale(1.004);
}

/* Slider pause/rewind pair (snippets/slider-controls.php) — pause top-
   right: 2% of the strip width (~2vw on the full-bleed strips) below its
   top, 2% past the shared gutter; diameter = the basket buttons'
   rendered height (--text-body + 0.3em pads + borders). Siblings of the
   .js-slider inside a relative wrapper, never children — pointer capture
   would swallow their clicks. */
.strip-pause,
.strip-rewind {
  position: absolute;
  top: 2vw;
  right: calc(var(--gutter) + 2%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: calc(1.6 * var(--text-body) + 2px);
  height: calc(1.6 * var(--text-body) + 2px);
  border: var(--border-thin);
  border-radius: var(--radius-pill);
  background: var(--color-paper);
  cursor: pointer;
  /* hold-to-rewind: without this a held finger's wobble reads as a
     scroll gesture and the browser pointercancels the press mid-hold;
     the selection/callout guards stop iOS long-press UI doing the same */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* left of pause with an 8px gap — the minimum recommended spacing
   between adjacent touch targets */
.strip-rewind {
  right: calc(var(--gutter) + 2% + 1.6 * var(--text-body) + 2px + 0.5rem);
}

.strip-pause .strip-pause__play-icon { display: none; }
.strip-pause[aria-pressed='true'] .strip-pause__pause-icon { display: none; }
.strip-pause[aria-pressed='true'] .strip-pause__play-icon { display: block; }

.product__slider-wrap {
  position: relative; /* anchors the slider-controls overlay */
}

/* the wrap IS the image box here (not a full-width strip), so the inset
   is measured from the image edge directly */
.product__slider-wrap .strip-pause {
  right: 2%;
}

.product__slider-wrap .strip-rewind {
  right: calc(2% + 1.6 * var(--text-body) + 2px + 0.5rem);
}

/* ---- desktop ---- */

@media (min-width: 72rem) {
  /* the gap is the arrow's foot plus .page's own top padding — halve both */
  .product__back {
    padding-bottom: 0.375rem;
  }

  /* auto column: the media is height-driven (fit-content below), so the
     column hugs the photo and the text always sits one gap away from it */
  .page.product {
    --text-col-stop: 6.6875rem; /* 107px in from the gutter — one right edge for the whole text column */
    padding-top: 0.125rem;
    display: grid;
    grid-template-columns: auto 1fr;
    /* explicit: the media column spans both rows, and two auto rows would
       split its height between them — the buy row would grow and the
       accordion's start (the rail's anchor) would shift on every section
       switch. 1fr pins all the slack in the accordion row. */
    grid-template-rows: auto 1fr;
    column-gap: var(--space-3);
    align-items: start;
  }

  /* the slider inside sizes itself to this box, so the slides follow
     automatically; fit-content keeps the box hugging the height-driven
     photo — the bestseller badge anchors to this box's corner */
  .product__media {
    grid-row: 1 / span 2;
    width: fit-content;
    max-width: 100%;
  }

  /* 3:4 like mobile, but height-driven: top level with the description
     column, bottom just above the fold, width following the ratio (a
     width-driven frame ran past the viewport). 9.3125rem = the 8.0625rem
     above the media (header + marquee + back row) plus bottom air. */
  .product__image,
  .product__slider {
    width: auto;
    max-width: 100%;
    height: calc(100svh - 9.3125rem);
  }

  /* the price rides the title's line; --text-col-stop is the column's
     shared right edge — body text, price and stock all end on it */
  .product__buy {
    grid-column: 2;
    padding: 0 var(--text-col-stop) 0 0;
    text-align: left;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
  }

  .product__buy > * {
    grid-column: 1 / -1;
  }

  /* pulled up by the leading above the caps (Inter's ascent minus its
     cap height, less the line-height's own negative half-leading) so the
     title's caps start level with the photo, not its line box */
  .product__title {
    grid-column: 1;
    grid-row: 1;
    margin-top: -0.21em;
  }

  .product__price {
    grid-column: 2;
    grid-row: 1;
    margin-top: 0;
    font-size: var(--text-menu); /* 36px */
    font-weight: var(--weight-regular);
    text-align: right;
  }

  .product__subtitle {
    grid-column: 1;
    grid-row: 2;
    font-size: 1.375rem; /* 22px — Vytas-tuned, between the 20/24 tokens */
    font-weight: var(--weight-light);
  }

  /* stock rides the type's line, under the price */
  .product__stock {
    grid-column: 2;
    grid-row: 2;
    font-size: 1.375rem; /* 22px, same as the type beside it */
    font-weight: var(--weight-light);
    text-align: right;
  }

  .accordion {
    grid-column: 2;
  }

  .related-pair {
    grid-column: 1 / -1;
  }

  .product__title {
    font-size: var(--text-heading); /* 32px */
  }

  .product__actions {
    justify-content: start;
  }

  /* both controls take the shop card's basket button: content-sized, with
     em padding so the box grows with the type */
  .product__qty,
  .product__basket {
    width: auto;
    height: auto;
    padding: 0.25em 0.9em;
    border-radius: var(--radius-m);
    font-size: var(--text-body); /* 20px */
    font-weight: var(--weight-regular);
    line-height: 1;
  }

  .product__qty {
    gap: 0.9em;
  }

  .product__qty-btn {
    min-width: 0;
    min-height: 0;
  }

  /* ---- accordion becomes a vertical icon rail + one panel ---- */

  /* The rail is lifted out of flow rather than laid out beside the panel:
     grid can't do it (a <details> keeps its own shadow slots between the
     grid and its children, so summary and content never become grid
     items — and display:contents is refused outright on a <button>), and
     floats can't either (a float never rises above the boxes before it,
     so the panel would start beside whichever icon is selected). With
     every summary absolute, the closed sections collapse to nothing and
     the open one's panel always starts at the top. */
  .accordion {
    position: relative;
    padding-left: 6.4125rem; /* 66.6px rail + its 36px gap — rail is the drawn 74px less 10% */
    margin-top: var(--space-5);
    /* the grid aligns items start — stretched, the accordion takes the
       row's photo-driven height, which the absolute panel below scrolls
       within instead of growing the page past the photo */
    align-self: stretch;
  }

  /* the rail's rhythm — one cell per section, in source order */
  .accordion__item { --row: 0; }
  .accordion__item:nth-child(2) { --row: 1; }
  .accordion__item:nth-child(3) { --row: 2; }
  .accordion__item:nth-child(4) { --row: 3; }
  .accordion__item:nth-child(5) { --row: 4; }
  .accordion__item:nth-child(6) { --row: 5; }
  .accordion__item:nth-child(7) { --row: 6; }

  /* mobile's stacked rows: the rail draws its own separators below.
     :last-child restated — it outranks a bare .accordion__item */
  .accordion__item,
  .accordion__item:last-child {
    border: 0;
    padding: 0;
  }

  .accordion__summary {
    position: absolute;
    left: 0;
    top: calc(var(--row) * 4.5rem); /* 72px pitch — the drawn 81px less 10% */
    width: 4.1625rem;
    height: 4.5rem;
  }

  /* same 3px + yellow as the default-address accent (auth.css) */
  .accordion__item + .accordion__item .accordion__summary {
    border-top: 3px solid #fff200;
  }

  .accordion__label {
    display: block;
    height: 100%;
  }

  .accordion__icon {
    width: 100%;
    height: 100%;
    padding-block: 0.675rem;
    /* contain, in a box that never changes size: the drawings have their
       own proportions, so anything else would move them cell to cell */
    object-fit: contain;
    /* drawn 15% smaller without touching the rail's cell geometry */
    scale: 0.85;
  }

  /* Chrome matches :focus-visible on a clicked summary — the global ink
     ring reads as a stray box around the icon; selection is already
     visible (opacity below), and keyboard toggling still works */
  .accordion__summary:focus-visible {
    outline: none;
  }

  .accordion__summary:focus-visible .accordion__icon {
    opacity: 1;
  }

  /* the rail reads as a set of choices: the one being read is full
     strength, the rest sit back */
  .accordion__item:not([open]) .accordion__icon {
    opacity: 0.4;
  }

  @media (hover: hover) {
    .accordion__item:not([open]) .accordion__icon:hover {
      opacity: 1;
    }
  }

  /* the section title belongs to the panel, not the rail — pulled back up
     out of its own (absolute) summary to the top of the panel column */
  .accordion__label-text {
    position: absolute;
    left: 6.4125rem;
    top: calc(var(--row) * -4.5rem);
    width: max-content; /* shrink-to-fit against the 66px summary box would wrap it */
    font-size: var(--text-title); /* 24px */
    font-weight: var(--weight-medium);
    line-height: 1.15;
  }

  .accordion__item:not([open]) .accordion__label-text {
    display: none;
  }

  /* the separator above sits inside the summary's box, and an absolute
     child offsets from the padding edge — without this, every title but
     the first lands 3px below the shared line */
  .accordion__item + .accordion__item .accordion__label-text {
    top: calc(var(--row) * -4.5rem - 3px);
  }

  /* a section without an icon shows its title in the rail cell instead —
     an empty invisible button would be unusable. Same dimmed-at-rest
     treatment as the icons. */
  .accordion__item--no-icon:not([open]) .accordion__label-text {
    display: grid;
    place-items: center;
    position: static;
    height: 100%;
    width: auto;
    font-size: var(--text-caption);
    text-align: center;
    line-height: 1.1;
    opacity: 0.4;
  }

  @media (hover: hover) {
    .accordion__item--no-icon:not([open]) .accordion__label-text:hover {
      opacity: 1;
    }
  }

  /* Out of flow like the summaries: the panel takes its height from the
     accordion box (photo-driven, align-self above) instead of setting it,
     and text that doesn't fit scrolls inside. Top offset clears the
     floating title; left matches the label-text's rail offset. */
  .accordion__item[open] .accordion__content {
    position: absolute;
    top: 2.5rem;
    right: var(--text-col-stop);
    bottom: 0;
    left: 6.4125rem;
    max-width: 50em; /* measure cap, same convention as legal.css */
    overflow-y: auto;
    margin-top: 0;
    padding-right: var(--space-2); /* lane for the scrollbar, off the text */
  }

  /* 17px, as the journal article's body — off the token scale, whose
     nearest steps are 16 and 20. Weight sits on the container ONLY and
     inherits down: a universal weight reset would also hit elements
     nested inside a bold run (the em of bold+italic) and strip it. */
  .accordion__content,
  .accordion__content * {
    font-size: 1.0625rem;
  }

  .accordion__content {
    font-weight: var(--weight-regular);
  }

  /* the rail has to stay inside the box even when the open panel is
     shorter than it — one rule per section count, tallest last */
  .accordion:has(.accordion__item:nth-child(4)) { min-height: 18rem; }
  .accordion:has(.accordion__item:nth-child(5)) { min-height: 22.5rem; }
  .accordion:has(.accordion__item:nth-child(6)) { min-height: 27rem; }
  .accordion:has(.accordion__item:nth-child(7)) { min-height: 31.5rem; }

  /* the +/− belongs to the accordion; here the rail is the control */
  .accordion__toggle {
    display: none;
  }
}
