/* =====================================================================
   Dunia Anura — "Berkas Spesimen": the page below the field book.

   The detail pages open with the book (css/sketchbook.css). Everything
   under it is this: the desk the book was made on, and the file the book
   was made from. It is deliberately narrower than the book at every width,
   it has one left edge, and its only section header is the book's own leaf
   furniture translated into the page's sans — a number, a tracked word, a
   hairline. No display heading below the book competes with the name set
   on the paper.

   Three grounds, read top to bottom: BOOK (paper, 12% radius on nothing) →
   DESK (square-ish, 12px slips, hairlines, tabular figures) → SHOP (the
   design system's 32px cards and 999px pills, in "Serupa"). The corner
   radius is what marks each change; it is the one deliberate departure from
   ds/styles.css and it is stated here rather than scattered.

   This file loads AFTER css/sketchbook.css, so at equal specificity it
   wins — which is why nothing in here needs !important. If you find
   yourself reaching for one, an inline style attribute was left behind in
   site-src/pages/*-detail.html. Take it out instead.
   ===================================================================== */

body[data-page="species-detail"],
body[data-page="product-detail"] {
  /* one measure for everything below the book — 1240 at 1440, which is the
     measure the related grid already used, so the page finally has a single
     left edge instead of a 1060 counter under a 1240 body */
  --dsr-w:    min(1400px, calc(100vw - clamp(20px, 7vw, 100px) * 2));
  --dsr-gap:  clamp(16px, 1.7vw, 24px);      /* every grid gutter          */
  --dsr-band: clamp(56px, 5.2vw, 84px);      /* band to band               */
  --dsr-end:  clamp(84px, 9vh, 120px);       /* last band to the footer    */

  /* inks. The page's own tokens where they exist; the plate's values where
     the plate is what is being echoed. */
  --dsr-rule:  var(--color-neutral-400);     /* the plate's RULE, one step
                                                darker so it holds on cream */
  --dsr-hair:  var(--color-divider);
  --dsr-warn:  #a8761d;                      /* IUCN VU/EN                 */
  --dsr-alarm: #96442b;                      /* Stok habis, IUCN CR/EW/EX  */
  --dsr-chop:  #a34a30;                      /* the plate's RED, verbatim  */
  --dsr-trace: #a89b83;                      /* the plate's trace grey     */
  --dsr-card:  0 1px 2px rgba(58, 44, 26, .10), 0 6px 18px rgba(58, 44, 26, .07);
  --dsr-slip-r: 12px;
  --dsr-serif: 'Instrument Serif', "New York", Georgia, serif;
}

.dsr      { width: var(--dsr-w); margin-inline: auto; }
/* scroll-margin: the nav is fixed at y 14..78 at every width, so a band
   reached by its id (#sdPanelBand in a shared URL) would land with its head
   under the pill — the same 96px the transcript's record already uses */
.dsr-band { margin-top: var(--dsr-band); scroll-margin-top: 96px; }
.dsr-last { padding-bottom: var(--dsr-end); }
.dsr *    { box-sizing: border-box; }

/* Two bands exist in one state only. Gating the whole section — not just its
   body — is what lets DA.numberBands() count what is actually on the page, so
   a missing band leaves no hole in the numbering. */
.dsr-onlybook { display: none; }
html.has-book .dsr-onlybook { display: block; }
html.has-book .dsr-proseband { display: none; }
/* The product's Deskripsi block exists for the book's transcript only: without
   the book the same paragraph is already the lede under the photograph
   (#pdDesc) — measured at 390 it was printed twice, 900px apart. And 115 of
   184 products carry no tips, so without that block their Notes band would
   hold nothing at all; js/pages/product-detail.js marks those .no-tips. */
html:not(.has-book) .dsr-bookonly { display: none; }
html:not(.has-book) .dsr-proseband.no-tips { display: none; }

/* the breadcrumb keeps the measure too, so the page's left edge starts at
   the very top rather than at the counter */
.detail-top { padding: 150px 0 0; }
html.has-book .detail-top { padding-top: 96px; }
html.has-book .detail-top > div { margin-bottom: 12px; }

/* ---------------------------------------------------------- numerals */
.dsr-head .n, .dsr-plate .n, .dsr-row dd, .dsr-price, .dsr-time,
.dsr-pick .s, .dsr-avail b, .dsr-viewn {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* ================================================ the band head ======
   furniture() from js/sketchbook-plate.js at page scale: the leaf number,
   the tracked word, the rule under both, and the running head on the right.
   This is the only section header below the book. */
.dsr-head {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline; column-gap: 20px;
  padding-bottom: 10px; margin-bottom: 26px;
  border-bottom: 1.5px solid var(--dsr-rule);
}
.dsr-head .l { display: flex; align-items: baseline; gap: 12px; min-width: 0; }
.dsr-head .n { font: 700 var(--fs-min)/1 var(--font-body); letter-spacing: .14em; color: var(--color-accent-700); }
.dsr-head .t { font: 700 var(--fs-read)/1 var(--font-body); letter-spacing: .2em; text-transform: uppercase; color: var(--color-text); }
.dsr-head .r {
  font: 600 var(--fs-read)/1.2 var(--font-body); letter-spacing: .1em;
  text-transform: uppercase; color: var(--color-neutral-600);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dsr-head .r.run { font: italic 400 14px/1.2 var(--dsr-serif); letter-spacing: 0; text-transform: none; }

/* ================================================ the key/value row ==
   the plate's table(): key in the page's sans, value in the book's italic */
.dsr-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px;
  align-items: baseline; padding: 9px 0;
  border-bottom: 1px solid var(--dsr-hair); font-size: var(--fs-read); margin: 0;
}
.dsr-row dt { color: var(--color-neutral-600); }
.dsr-row dd { margin: 0; text-align: right; color: var(--color-neutral-800);
              font: italic 400 15.5px/1.35 var(--dsr-serif); }
.dsr-row:last-child { border-bottom: 0; }
.dsr-dl { margin: 0; }

/* ============================================ 01 · KETERANGAN ========
   Band 01 does not take --dsr-band: the counter has to keep peeking under
   the book, which is what invites the scroll. */
.dsr-counterband { margin-top: clamp(26px, 4vh, 44px); }

.dsr-ledger {
  display: grid; grid-template-columns: minmax(0, auto) minmax(24px, 1fr) auto;
  align-items: baseline; column-gap: 14px; margin-bottom: 26px;
}
.dsr-ledger h1 {
  margin: 0; font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: clamp(28px, 2.4vw, 36px); line-height: 1.06;
  letter-spacing: -.015em; min-width: 0; text-wrap: balance;
}
.dsr-leader {
  height: 0; font-size: 28px; align-self: baseline;
  border-bottom: 1.5px dotted color-mix(in srgb, var(--color-text) 26%, transparent);
  transform: translateY(-.28em);
}
.dsr-price {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: clamp(22px, 1.9vw, 28px); line-height: 1.05;
  color: var(--color-accent); white-space: nowrap;
}

.dsr-counter { display: grid; grid-template-columns: minmax(0, 1fr) 400px; column-gap: 56px; align-items: start; }
.dsr-facts   { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.dsr-tags    { display: flex; gap: 8px; flex-wrap: wrap; }
/* .tag-neutral is #f2ece0 on #ece7dc here — all but invisible. Give it the
   card's ground and a hairline so it reads as a chip at all. */
.dsr-tags .tag-neutral { background: var(--color-surface); box-shadow: inset 0 0 0 1px var(--dsr-hair); }
.dsr-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; font-size: var(--fs-read); color: var(--color-neutral-600); }
.dsr-meta > span { display: inline-flex; align-items: center; gap: 7px; }
.dsr-lede { margin: 0; font-size: 15px; line-height: 1.75; color: var(--color-neutral-700); max-width: 62ch; }

/* ---- the slip: the one object on the page that carries the transaction */
.dsr-buy {
  position: relative; background: var(--color-surface);
  border-radius: var(--dsr-slip-r); padding: 20px 22px 26px;
  box-shadow: var(--dsr-card); display: flex; flex-direction: column; gap: 16px;
}
.dsr-buy hr { border: 0; border-top: 1px solid var(--dsr-hair); margin: 0; }
.dsr-cap { font: 700 var(--fs-read)/1 var(--font-body); letter-spacing: .2em; text-transform: uppercase; color: var(--color-neutral-600); }
.dsr-avail { display: grid; grid-template-columns: auto auto; justify-content: space-between; align-items: baseline; gap: 12px; }
.dsr-avail b { font-size: 14px; font-weight: 700; color: var(--color-accent-700); }
.dsr-avail b.out { color: var(--dsr-alarm); }

.dsr-pickbox { display: flex; flex-direction: column; gap: 10px; }
.dsr-pick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; align-items: stretch; }
.dsr-pick .pick-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  border: 1.5px solid var(--dsr-hair); border-radius: 10px; padding: 10px 12px;
  background: var(--color-bg); color: var(--color-text); cursor: pointer;
  font-family: var(--font-body); font-size: 14px; font-weight: 600; text-align: left;
  transition: border-color .18s ease, background-color .18s ease, color .18s ease;
}
.dsr-pick .pick-btn .s { font-size: var(--fs-read); font-weight: 500; opacity: .75; }
.dsr-pick .pick-btn:hover:not([disabled]) { border-color: var(--color-accent-400); }
.dsr-pick .pick-btn[aria-pressed="true"] { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-bg); }
.dsr-pick .pick-btn[disabled] { background: var(--color-neutral-200); border-color: var(--color-neutral-200); color: var(--color-neutral-500); cursor: not-allowed; text-decoration: line-through; }
/* 7-12 options: chips, label only, availability on one line beneath */
.dsr-pick.compact { display: flex; flex-wrap: wrap; gap: 8px; }
.dsr-pick.compact .pick-btn { border-radius: 999px; padding: 8px 14px; flex-direction: row; }
.dsr-pick.compact .pick-btn .s { display: none; }
.dsr-picknote { font-size: var(--fs-read); color: var(--color-neutral-600); }
.dsr-pickbox select.input { width: 100%; }

.dsr-act { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 12px; }
.dsr-act .dsr-step {
  grid-column: 1; display: flex; align-items: center; justify-content: space-between;
  border: 1.5px solid var(--dsr-hair); border-radius: 999px; overflow: hidden; background: var(--color-bg);
}
.dsr-act .dsr-step .qty-btn { border: none; background: transparent; width: 42px; height: 44px; font-size: 18px; cursor: pointer; color: var(--color-text); }
.dsr-act .dsr-step span { min-width: 32px; text-align: center; font-weight: 700; font-size: 15px; }
.dsr-act #addCart { grid-column: 2; width: 100%; justify-content: center; }
.dsr-act #buyNow  { grid-column: 1 / -1; width: 100%; justify-content: center; }

.dsr-ship { display: flex; flex-direction: column; gap: 8px; font-size: var(--fs-read); color: var(--color-neutral-600); max-width: calc(100% - 68px); }
.dsr-ship span { display: flex; gap: 8px; align-items: flex-start; }
.dsr-ship svg { width: 15px; height: 15px; flex: none; margin-top: 2px; color: var(--color-accent-700); }

/* the breeder's stamp — exactly one on the page, and it lands on the slip,
   which is where the charm belongs */
.dsr-chop { position: absolute; right: 16px; bottom: 14px; width: 56px; height: 56px; transform: rotate(-5deg); opacity: .28; color: var(--dsr-chop); pointer-events: none; }

/* ============================================ 02 · GAMBAR ============ */
.dsr-plates { display: none; }
html.has-book .dsr-plates { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--dsr-gap); }
.dsr-plate { margin: 0; min-width: 0; }
.dsr-shot {
  display: block; width: 100%; aspect-ratio: 1; padding: 0; border: 0; cursor: zoom-in;
  overflow: hidden; border-radius: 4px; background: var(--color-surface);
  box-shadow: inset 0 0 0 1px var(--dsr-hair);
}
.dsr-shot img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .7s cubic-bezier(.22, 1, .36, 1); }
/* plate 01 is a specimen cut out on paper: it is shown whole, not cropped */
.dsr-shot.contain img { object-fit: contain; padding: 7%; }
.dsr-plate:hover .dsr-shot img { transform: scale(1.035); }
.dsr-plate figcaption {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px;
  align-items: baseline; margin-top: 10px; padding-top: 8px;
  border-top: 1px solid var(--dsr-hair);
  font: 600 var(--fs-read)/1.2 var(--font-body); letter-spacing: .14em; text-transform: uppercase;
}
.dsr-plate figcaption .n { color: var(--color-accent-700); }
.dsr-plate figcaption .c { color: var(--color-neutral-600); }
/* it used to be nowrap + ellipsis in a column that measured 123px at 1280 while
   "IN THE ENCLOSURE" needed 122px at the OLD 10.5px/.14em — i.e. it was already
   truncating. Letting it wrap frees the caption from the third column without
   moving .dsr-toleaf onto a second row, where it would reserve ~20px of blank
   space under every plate for a control that is invisible until hover. */
.dsr-toleaf { border: 0; background: none; padding: 0; cursor: pointer; font: inherit; color: var(--color-accent-700); opacity: 0; transition: opacity .2s ease; white-space: nowrap; }
.dsr-plate:hover .dsr-toleaf, .dsr-toleaf:focus-visible { opacity: 1; }
/* fewer than four photographs: the row terminates on purpose */
.dsr-platenote { font-size: 15px; line-height: 1.75; color: var(--color-neutral-700); max-width: 46ch; align-self: start; }
.dsr-platenote.tight { font-size: var(--fs-read); }

/* ============================================ 03 · REKAMAN =========== */
.dsr-rec { display: grid; grid-template-columns: 352px minmax(0, 1fr); column-gap: 44px; row-gap: 26px; align-items: start; }
.dsr-rec.voice-only { grid-template-columns: minmax(0, 1fr); }
.dsr-filmwrap { min-width: 0; }
.dsr-film {
  position: relative; width: 352px; max-width: 100%; aspect-ratio: 1;
  overflow: hidden; border-radius: 6px; background: #221e18;
  box-shadow: inset 0 0 0 1px rgba(58, 44, 26, .28), var(--dsr-card);
}
.dsr-film video { width: 100%; height: 100%; display: block; object-fit: contain; background: #221e18; }
.dsr-film > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dsr-veil { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(28, 24, 18, .42), rgba(28, 24, 18, .66)); }
.dsr-play {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px;
  border: 0; background: transparent; cursor: pointer;
  color: rgba(250, 246, 238, .92); font-family: var(--font-body); font-size: var(--fs-read); letter-spacing: .04em;
  transition: background-color .2s ease, color .2s ease;
}
.dsr-play .ring {
  width: 64px; height: 64px; border-radius: 50%; border: 1.5px solid currentColor;
  display: grid; place-items: center; transition: transform .2s ease;
}
.dsr-play .ring svg { width: 22px; height: 22px; fill: currentColor; margin-left: 3px; }
.dsr-play:hover { background: rgba(255, 250, 240, .10); color: #fffaf0; }
.dsr-play:hover .ring { transform: scale(1.05); }
.dsr-film .honest {
  position: absolute; left: 14px; bottom: 12px; pointer-events: none;
  font: 600 var(--fs-read)/1.2 var(--font-body); letter-spacing: .16em; text-transform: uppercase;
  color: rgba(246, 242, 233, .72);
}
/* no enclosure photograph to rest on: the panel says so in type instead */
.dsr-film.blank { background: var(--color-surface); box-shadow: inset 0 0 0 1px var(--dsr-hair), var(--dsr-card); }
.dsr-film.blank .dsr-play { color: var(--color-accent-700); }
.dsr-film.blank .honest { color: var(--color-neutral-500); }

.dsr-filmcap {
  display: grid; grid-template-columns: auto auto; justify-content: space-between;
  margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--dsr-hair);
  font: 600 var(--fs-read)/1.2 var(--font-body); letter-spacing: .14em; text-transform: uppercase; color: var(--color-neutral-600);
}
.dsr-recnote { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.dsr-recnote p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--color-neutral-700); max-width: 46ch; }
/* a two-row table stretched across 840px puts a chasm between key and
   value; it keeps the note's measure instead */
.dsr-recnote .dsr-dl { max-width: 46ch; }

/* beside a 352px film the slip takes the rest of the measure — the trace
   stretches, so a wider one is simply a longer recording to look at.
   Alone on a full-width row it would be absurd, hence the cap. */
.dsr-call { background: var(--color-surface); border-radius: var(--dsr-slip-r); box-shadow: var(--dsr-card); padding: 18px 20px; }
.dsr-rec.voice-only .dsr-call { max-width: 560px; }
.dsr-call > .dsr-cap { display: block; padding-bottom: 10px; border-bottom: 1.5px solid var(--dsr-rule); }
.dsr-callrow { display: grid; grid-template-columns: 46px auto minmax(0, 1fr); gap: 16px; align-items: center; padding: 16px 0 12px; }
.dsr-call .vplay { width: 46px; height: 46px; flex: none; border: none; border-radius: 50%; background: var(--color-accent); color: var(--color-bg); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 15px; }
.dsr-time { font-size: var(--fs-read); font-weight: 600; color: var(--color-neutral-700); min-width: 84px; }
.dsr-call svg.trace { display: block; width: 100%; height: 34px; }
.dsr-callcap { font: italic 400 14px/1.3 var(--dsr-serif); color: var(--color-neutral-600); }
.dsr-callsub { margin-top: 6px; font: 600 var(--fs-read)/1.2 var(--font-body); letter-spacing: .14em; text-transform: uppercase; color: var(--color-neutral-500); }

/* ============================================ 04 · BERKAS ============ */
.sbk.sbk-notes { background: transparent; padding: 0; font-family: var(--font-body); color: var(--color-text); }
.sbk .sbk-transcript { max-width: none; margin: 0; }
.sbk .sbk-transcript > summary {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 14px; align-items: center;
  padding: 16px 0; border: 0; border-bottom: 1px solid var(--dsr-hair);
  border-radius: 0; background: transparent; font-size: 14px; letter-spacing: .02em;
  transition: background-color .25s ease;
}
.sbk .sbk-transcript > summary:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.sbk .sbk-transcript #sdRecord { max-width: 78ch; padding: 26px 0 0; scroll-margin-top: 96px; }

/* The product's tips come as paragraphs separated by blank lines, and a line
   that opens with a check mark is the heading of the paragraph after it.
   Poured in as one text node they were a single block — 2,887px tall at 390
   on the longest record. js/pages/product-detail.js splits them here. */
.dsr-tips p { margin: 0 0 12px; }
.dsr-tips p:last-child { margin-bottom: 0; }
.dsr-tips .dsr-tip-h { margin-bottom: 4px; font-weight: 700; color: var(--color-text); }

/* On a phone the species record is a list of closed sections — the same +/−
   summary the transcript uses (css/sketchbook.css:353), on the desk's hairline.
   Open, the 3–7 sections were one 1,200–4,600px column at 390 with the care
   sheet below all of it. The markup is the gate: js/pages/species-detail.js
   only emits .dsr-fold at ≤640, so a tablet turned sideways keeps its styling. */
.dsr-fold { border-bottom: 1px solid var(--dsr-hair); }
.dsr-fold > summary {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 14px; align-items: center;
  min-height: 52px; padding: 12px 0; cursor: pointer; list-style: none;
}
.dsr-fold > summary::-webkit-details-marker { display: none; }
.dsr-fold > summary::before { content: "+"; width: 18px; text-align: center; font-size: 20px; line-height: 1; color: var(--color-neutral-500); }
.dsr-fold[open] > summary::before { content: "\2212"; }
.dsr-fold > summary h2 { margin: 0; font-size: 18px; line-height: 1.2; }
.dsr-fold > p { margin: 0 0 22px; font-size: 15px; line-height: 1.75; color: var(--color-neutral-700); white-space: pre-line; text-wrap: pretty; }

/* ============================================ 05 · DATA ============== */
.dsr-panel {
  display: grid; gap: 0; background: var(--color-surface);
  border-radius: var(--dsr-slip-r); box-shadow: var(--dsr-card); padding: 32px 36px 28px;
}
.dsr-panel[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.dsr-panel[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dsr-panel[data-cols="1"] { grid-template-columns: minmax(0, 1fr); }
.dsr-block { display: flex; flex-direction: column; padding-inline: 28px; min-width: 0; }
.dsr-block:first-child { padding-left: 0; }
.dsr-block:last-child  { padding-right: 0; }
.dsr-block + .dsr-block { border-left: 1px solid var(--dsr-hair); }
.dsr-block > h3 {
  font: 700 var(--fs-read)/1 var(--font-body); letter-spacing: .2em; text-transform: uppercase;
  color: var(--color-neutral-600); margin: 0 0 6px; padding-bottom: 10px;
  border-bottom: 1.5px solid var(--dsr-rule);
}
.dsr-block > h3 + * { margin-top: 6px; }
.dsr-block > h3.mid { margin-top: 24px; }
.dsr-iucn { display: flex; align-items: center; gap: 12px; margin: 12px 0 4px; }
.dsr-iucn .code { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 22px; color: var(--color-bg); background: var(--color-accent); border-radius: 6px; padding: 5px 12px; }
.dsr-iucn .code.warn  { background: var(--dsr-warn); }
.dsr-iucn .code.alarm { background: var(--dsr-alarm); }
.dsr-iucn .code.na    { background: var(--color-neutral-500); }
.dsr-iucn .lab { font-size: 14px; font-weight: 600; }
.dsr-flag { display: inline-block; width: 22px; height: 16.5px; border-radius: 3px; background-size: cover; background-position: center; box-shadow: var(--shadow-sm); flex: none; vertical-align: -2px; margin-left: 8px; }
.dsr-map { position: relative; margin-top: 14px; border: 1px solid var(--dsr-hair); border-radius: 8px; overflow: hidden; background: var(--color-neutral-100); }
.dsr-map iframe { width: 100%; height: 200px; border: none; display: block; }
.dsr-map .loading { position: absolute; inset: 0; display: grid; place-items: center; font-size: var(--fs-read); color: var(--color-neutral-500); pointer-events: none; }
.dsr-maplink { display: block; text-align: right; margin-top: 10px; font-size: var(--fs-read); font-weight: 700; }
.dsr-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }

/* ============================================ 06 · ULASAN ============ */
.dsr-revempty { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 18px; align-items: center; min-height: 76px; font-size: 14.5px; color: var(--color-neutral-600); }
.dsr-revfull { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--dsr-gap); align-items: start; }

/* ============================================ 07 · SERUPA =========== */
/* the desk ends and the shop begins — and the corner radius says so */
.dsr-relsub { margin: 0 0 22px; font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 20px; line-height: 1.2; color: var(--color-neutral-700); }
.dsr-rel { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--dsr-gap); }
/* the card's padding and title size used to be style attributes written by
   the two page scripts; they are here so the phone rule can change them */
.dsr-rel .card { padding: 12px 12px 18px; }
.dsr-rel .card-title { font-size: 16.5px; }
body[data-page="product-detail"] .dsr-rel .card-title { font-size: 16px; line-height: 1.25; }

/* ============================================ the viewer ============ */
#dsrView {
  position: fixed; inset: 0; z-index: 240; display: none;
  background: color-mix(in srgb, #ece7dc 92%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
#dsrView.open { display: grid; grid-template-rows: 1fr auto; place-items: center; padding: clamp(24px, 4vh, 56px); }
#dsrView img { max-width: min(1100px, 92vw); max-height: 78vh; object-fit: contain; border-radius: 6px; box-shadow: 0 24px 60px rgba(58, 44, 26, .28); background: var(--color-surface); }
#dsrView .bar {
  width: min(1100px, 92vw); display: grid; grid-template-columns: auto auto;
  justify-content: space-between; align-items: baseline; margin-top: 16px; padding-top: 10px;
  border-top: 1px solid var(--dsr-hair);
  font: 600 var(--fs-min)/1.2 var(--font-body); letter-spacing: .14em; text-transform: uppercase; color: var(--color-neutral-600);
}
#dsrView .x, #dsrView .dsr-nav {
  position: absolute; border: 0; padding: 0; cursor: pointer; color: var(--color-text);
  background: var(--color-surface); box-shadow: var(--dsr-card);
  width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
}
#dsrView .x { top: clamp(16px, 3vh, 32px); right: clamp(16px, 3vw, 32px); font-size: 18px; }
#dsrView .x svg { width: 17px; height: 17px; display: block; }
#dsrView .dsr-nav svg { width: 21px; height: 21px; display: block; }
#dsrView .dsr-nav { top: 50%; transform: translateY(-50%); font-size: 20px; }
#dsrView .dsr-nav.prev { left: clamp(10px, 2vw, 28px); }
#dsrView .dsr-nav.next { right: clamp(10px, 2vw, 28px); }
#dsrView .x:hover, #dsrView .dsr-nav:hover { background: var(--color-bg); }

/* ================================ the no-book page ==================
   Below about 1015px the book is never drawn, so this is what a phone
   gets — and it is the same document, not a lesser one: the same bands,
   the same heads, the same measure. Four differences only. */
html:not(.has-book) .dsr-counter { grid-template-columns: minmax(300px, 480px) minmax(0, 1fr); column-gap: 56px; row-gap: 24px; }
/* the gallery spans both rows so that sticky has something to stick within */
html:not(.has-book) .dsr-counter > .detail-media { grid-column: 1; grid-row: 1 / span 2; position: sticky; top: 100px; align-self: start; display: flex; flex-direction: column; gap: 14px; min-width: 0; }
html:not(.has-book) .dsr-facts { grid-column: 2; grid-row: 1; }
html:not(.has-book) .dsr-buy   { grid-column: 2; grid-row: 2; }
html:not(.has-book) .dsr-counter > .detail-media .shot { display: block; width: 100%; aspect-ratio: 1; background-size: cover; background-position: center; background-color: var(--color-surface); border-radius: var(--dsr-slip-r); box-shadow: var(--dsr-card); cursor: zoom-in; border: 0; padding: 0; }
html:not(.has-book) .dsr-counter > .detail-media .thumbs { display: flex; gap: 10px; flex-wrap: wrap; }
/* the thumb's size was inline in both page scripts; with the book up the
   whole .detail-media is hidden, so no has-book gate is needed here */
.detail-media .thumb-btn > span { width: 64px; height: 64px; }
/* the same four photographs are the gallery two columns to the left; a
   register under it would be the same pictures twice */
html:not(.has-book) .dsr-plates { display: none; }
/* a slip floating beside a photograph on bare paper is one panel too many */
html:not(.has-book) .dsr-buy { background: transparent; box-shadow: none; border-radius: 0; padding: 0; }
html:not(.has-book) .dsr-chop { right: 0; bottom: -6px; }
html.has-book .detail-media { display: none; }
html.has-book .dsr-proseband { display: none; }

/* ============================================ breakpoints =========== */
@media (max-width: 1180px) {
  .dsr-counter { grid-template-columns: minmax(0, 1fr) 340px; column-gap: 40px; }
  .dsr-buy { padding: 18px 18px 24px; }
  .dsr-map iframe { height: 180px; }
}
@media (max-width: 1014px) {
  .dsr-counter { grid-template-columns: minmax(280px, 420px) minmax(0, 1fr); }
  .dsr-rec { grid-template-columns: minmax(0, 1fr); }
  .dsr-rel { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 939px) {
  /* site.css flattens .detail-grid here, but that is #sdBuy itself; the
     counter is a grid one level in, so it has to be told separately. Both
     selectors are repeated at the specificity of the no-book rules above so
     that source order decides, and no !important is needed. */
  .dsr-counter,
  html:not(.has-book) .dsr-counter { grid-template-columns: minmax(0, 1fr); row-gap: 26px; }
  html:not(.has-book) .dsr-counter > .detail-media { grid-column: 1; grid-row: 1; position: static; }
  html:not(.has-book) .dsr-facts { grid-column: 1; grid-row: 2; }
  html:not(.has-book) .dsr-buy   { grid-column: 1; grid-row: 3; }
  html:not(.has-book) .dsr-counter > .detail-media .shot { max-width: 520px; }
  .dsr-plates { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dsr-rec { grid-template-columns: minmax(0, 1fr); }
  .dsr-film { width: 100%; max-width: 420px; }
  .dsr-panel { grid-template-columns: minmax(0, 1fr) !important; padding: 24px 22px; }
  .dsr-block { padding-inline: 0; }
  .dsr-block + .dsr-block { border-left: 0; border-top: 1px solid var(--dsr-hair); padding-top: 22px; margin-top: 22px; }
  .dsr-rel { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
  .dsr-revfull { grid-template-columns: minmax(0, 1fr); }
  .detail-top { padding-top: 120px; }
}
@media (max-width: 640px) {
  .dsr-ledger { grid-template-columns: minmax(0, 1fr); }
  .dsr-leader { display: none; }
  .dsr-act { grid-template-columns: minmax(0, 1fr); }
  .dsr-act .dsr-step, .dsr-act #addCart, .dsr-act #buyNow { grid-column: 1; }
  .dsr-panel { padding: 20px 18px; }
  .dsr-map iframe { height: 170px; }
  /* the 28px floor never stepped down: a 63-character product name was four
     28px lines at 360. 7vw is 25.2px there, 27.3px at 390. */
  .dsr-ledger h1 { font-size: clamp(23px, 7vw, 28px); }
  /* the last crumb repeats that same name in two lines right above the h1 */
  .detail-top #bcName { min-width: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* the call: 46 + 84 + two gaps left the trace 133px for 52 bars at 390
     (108px at 360). It takes the whole slip on its own row instead. */
  .dsr-callrow { grid-template-columns: 46px minmax(0, 1fr); row-gap: 10px; }
  .dsr-callrow > span:last-child { grid-column: 1 / -1; }
  /* "MP3 · LOADS WHEN YOU PRESS PLAY" at .14em is 300px; at .04em it is 265px,
     one line inside the 270px slip at 360 */
  .dsr-callsub { letter-spacing: .04em; }
  /* Serupa: auto-fill minmax(230px) is one column at 335px, four cards of
     425px each — 1,750px of scroll for four links. Two across instead. */
  .dsr-rel { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .dsr-rel .card { padding: 8px 8px 14px; }
  .dsr-rel .card-title,
  body[data-page="product-detail"] .dsr-rel .card-title {
    font-size: var(--fs-read); line-height: 1.25;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
  }
  /* The viewer. The grid's one auto column was sized by the image (94vw) and
     the bar (92vw), both wider than the 322px content box the 4vh padding
     left, so both ran 10px past the right edge; and the arrows, dropped to
     the bottom, sat on the caption row. Pin the track to the padding box,
     keep the bar's text between the two 40px arrows, and centre all three on
     one 40px row. */
  #dsrView.open { padding: 72px 12px 20px; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
  #dsrView img { max-width: 100%; max-height: 100%; width: auto; }
  /* the arrows end 50px from either edge and the bar starts at 12, so 44px
     clears them; at .14em the longest caption plus counter needed 264px of
     the 248px left at 360, at .08em they need 239 */
  #dsrView .bar {
    width: 100%; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px;
    margin-top: 12px; padding: 0 44px; min-height: 40px; align-items: center; letter-spacing: .08em;
  }
  #dsrView .cap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #dsrView .dsr-nav { top: auto; bottom: 20px; transform: none; }
}
@media (max-width: 420px) {
  .dsr-head .r { display: none; }
  .dsr-plate figcaption { font-size: var(--fs-read); }
  /* four 74px thumbs at a 10px gap need 326px; the measure at 360 is 310 */
  .detail-media .thumb-btn > span { width: 56px; height: 56px; }
  html:not(.has-book) .dsr-counter > .detail-media .thumbs { gap: 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .dsr-shot img, .dsr-toleaf, .dsr-play, .dsr-play .ring, .dsr-pick .pick-btn { transition: none; }
}
