/* Shared wayfinding chrome for every child page.
   It sits above each page so a visitor can leave or return
   without hunting a header that has already scrolled away. */
:root {
  --qb-page-gutter: clamp(1rem, 4vw, 4.5rem);
  --qb-content-max: 90rem;
  --qb-content-width: min(calc(100% - (var(--qb-page-gutter) * 2)), var(--qb-content-max));
  --qb-chrome-size: 3rem;
  --qb-chrome-gap: var(--space-6, 32px);
  --qb-chrome-center-y: calc(max(var(--qb-chrome-gap), env(safe-area-inset-top, 0px)) + max(44px, var(--qb-chrome-size)) / 2);
  --qb-chrome-clear-block: calc(max(var(--qb-chrome-gap), env(safe-area-inset-top, 0px)) + var(--qb-chrome-size) + var(--qb-chrome-gap));
  --qb-chrome-clear-inline: calc(max(var(--qb-chrome-gap), env(safe-area-inset-left, 0px)) + max(44px, var(--qb-chrome-size)) + var(--qb-chrome-gap));
  /* Both percentages resolve against the header's containing block. Mixing
     100vw with that width loses half the reserved scrollbar gutter. */
  --qb-back-overlap-clear: max(0px, calc(var(--qb-chrome-clear-inline) - ((100% - var(--qb-content-width)) / 2)));
  /* Frosted glass (毛玻璃): a milky, evenly diffused fill, a hairline rim,
     one faint top-edge catch, and a soft short shadow. No specular blob.
     Every token follows the page's `color-scheme`: a light page gets the
     pale lens, a dark page gets charcoal, and a page that follows the system
     (`color-scheme: light dark`) switches with it. A route never has to opt
     in with its own six tokens; it declares its scheme and the glass matches. */
  --qb-chrome-ink: light-dark(#1c1914, #eef2f0);
  --qb-chrome-fill: light-dark(
    color-mix(in srgb, #faf8f1 62%, transparent),
    color-mix(in srgb, #121512 66%, transparent));
  --qb-chrome-fill-hover: light-dark(
    color-mix(in srgb, #faf8f1 80%, transparent),
    color-mix(in srgb, #1b201c 82%, transparent));
  --qb-chrome-shine: light-dark(
    color-mix(in srgb, white 28%, transparent),
    color-mix(in srgb, white 10%, transparent));
  --qb-chrome-rim: light-dark(
    color-mix(in srgb, #1c1914 10%, transparent),
    color-mix(in srgb, #eef2f0 16%, transparent));
  --qb-chrome-shadow: light-dark(
    color-mix(in srgb, #14110c 8%, transparent),
    color-mix(in srgb, black 28%, transparent));
}

.qb-chrome__back,
.qb-chrome__top {
  position: fixed;
  z-index: 16;
}

.qb-chrome__back {
  top: max(var(--qb-chrome-gap), env(safe-area-inset-top, 0px));
  left: max(var(--qb-chrome-gap), env(safe-area-inset-left, 0px));
}


.qb-chrome__top {
  right: max(var(--qb-chrome-gap), env(safe-area-inset-right, 0px));
  bottom: max(var(--qb-chrome-gap), env(safe-area-inset-bottom, 0px));
}

.qb-chrome__btn {
  isolation: isolate;
  display: grid;
  place-items: center;
  width: var(--qb-chrome-size);
  height: var(--qb-chrome-size);
  min-width: 44px;
  min-height: 44px;
  border: 1px solid var(--qb-chrome-rim);
  border-radius: 999px;
  color: var(--qb-chrome-ink);
  background: var(--qb-chrome-fill);
  box-shadow:
    inset 0 1px 0 var(--qb-chrome-shine),
    0 2px 8px var(--qb-chrome-shadow);
  backdrop-filter: blur(28px) saturate(1.05);
  -webkit-backdrop-filter: blur(28px) saturate(1.05);
  text-decoration: none;
}

/* Page link rules (`.restaurant-study a { color: inherit }`) outrank a
   single class. The nav-scoped selector keeps the icon on the chrome ink. */
.qb-chrome .qb-chrome__btn,
.qb-chrome .qb-chrome__btn:hover,
.qb-chrome .qb-chrome__btn:focus-visible {
  color: var(--qb-chrome-ink);
}

.qb-chrome__btn svg {
  position: relative;
  z-index: 1;
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
}

/* Keep state specificity low so the solid reduced-transparency surface wins. */
.qb-chrome__btn:where(:hover, :focus-visible) {
  background: var(--qb-chrome-fill-hover);
}

.qb-chrome__btn:where(:active) {
  background: var(--qb-chrome-fill-hover);
  box-shadow: inset 0 1px 2px var(--qb-chrome-shadow);
}

.qb-chrome__btn:focus-visible {
  outline: 3px solid #d2352c;
  outline-offset: 3px;
  border-radius: 999px;
}

html[data-qb-chrome]:not([data-qb-scrolled]) .qb-chrome__top {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(.35rem);
}

body:has(.qb-chrome) :is(.skip-link, .salon-skip):focus {
  z-index: 17;
  top: max(var(--qb-chrome-gap), env(safe-area-inset-top, 0px));
  left: var(--qb-chrome-clear-inline);
  transform: none;
}

@media (prefers-reduced-motion: no-preference) {
  .qb-chrome__btn {
    transition:
      background-color 180ms cubic-bezier(.16, 1, .3, 1),
      transform 180ms cubic-bezier(.16, 1, .3, 1),
      opacity 180ms cubic-bezier(.16, 1, .3, 1),
      box-shadow 180ms cubic-bezier(.16, 1, .3, 1);
  }

  .qb-chrome__btn:hover {
    transform: translateY(-.12rem);
  }

  .qb-chrome__btn:active {
    transform: translateY(0) scale(.96);
  }

}

/* Reserve only the inline pixels the outer gutter cannot supply. Unlike the
   retired spacer, this never adds vertical space and becomes zero on wide
   viewports. Corner Table's canonical row sits one level inside its header. */
body:has(.qb-chrome) > header:first-of-type {
  padding-inline-start: var(--qb-back-overlap-clear);
}

/* Sibling utility headers share the control's centerline, including when
   text or the hit target grows. Authored multi-row headers remain local. */
body:has(.qb-chrome) > :is(.plate-head, .rose-head) {
  min-height: 0;
  padding-block: calc(var(--qb-chrome-center-y) - .65em) var(--space-5, 24px);
  font-size: .78rem;
  line-height: 1.3;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .qb-chrome__btn {
    transition: none !important;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .qb-chrome__btn {
    background: light-dark(#f3f2ea, #18211e);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* Child-page imagery stays in its authored composition instead of spawning
   the browser's native drag preview. */
body:has(.qb-chrome) img {
  -webkit-user-drag: none;
  user-select: none;
}

/* The gallery's wayfinding belongs to its low-lit room. These variables and
   states are deliberately scoped: child routes retain the shared light glass. */
.gallery-page {
  --qb-chrome-ink: var(--gallery-ink);
  --qb-chrome-fill: color-mix(in srgb, var(--gallery-glass) 74%, transparent);
  --qb-chrome-fill-hover: color-mix(in srgb, var(--gallery-glass) 88%, transparent);
  --qb-chrome-shine: color-mix(in srgb, var(--gallery-light) 10%, transparent);
  --qb-chrome-rim: color-mix(in srgb, var(--gallery-light) 22%, transparent);
  --qb-chrome-shadow: color-mix(in srgb, var(--gallery-floor) 40%, transparent);
}

.gallery-page .qb-chrome__btn:focus-visible {
  outline-color: var(--gallery-cinnabar);
}

.gallery-page .qb-chrome__btn:where(:active) {
  background: color-mix(in srgb, var(--gallery-glass) 96%, transparent);
}

@media (prefers-reduced-transparency: reduce) {
  .gallery-page .qb-chrome__btn {
    background: var(--gallery-glass-solid);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* The shared listener rests as one whole disc floating clear of the viewport
   edge, at every width, while the deck chassis stays invisible. Hover,
   keyboard focus, or opening the panel slides the whole turntable into view
   and fades the chassis in. Controls materialize as smoked glass only after
   the visitor asks for them. */
.qb-player {
  --qb-player-glass: color-mix(in srgb, #172019 78%, transparent);
  --qb-player-glass-control: color-mix(in srgb, white 12%, transparent);
  position: fixed;
  z-index: 18;
  top: 50%;
  right: max(0px, env(safe-area-inset-right, 0px));
  color: #f5f3ea;
  font-family: var(--font-body, "IBM Plex Sans", sans-serif);
  line-height: 1.35;
  /* The dock's own box is the record button's untransformed layout box, but
     the rest state paints only the disc the button is slid and scaled down
     to, which leaves a wide strip of the wrapper with nothing in it. That
     strip sits over the copy column, so it must not swallow clicks or text
     selection: the wrapper stays transparent to the pointer and each
     interactive part below takes its own hits back. */
  pointer-events: none;
  transform: translateY(-50%);
}

.qb-player__record,
.qb-player__panel,
.qb-player__restore {
  pointer-events: auto;
}

.qb-player button,
.qb-player input,
.qb-player a {
  font: inherit;
}

.qb-player__record {
  --qb-deck-reveal: 0;
  display: grid;
  width: 7.2rem;
  height: 5.7rem;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: .9rem;
  color: #f5f3ea;
  background: transparent;
  cursor: pointer;
  /* Dock: one whole disc, never a cut one, resting at the size of the site's
     own control (--qb-chrome-size, 3rem) so it reads as chrome rather than as
     artwork that ran off the page. 4.6rem of vinyl scaled by .652 is 3rem,
     and the slide leaves .5rem of margin outside it: 56px of reserved edge in
     total, which is the widest the copy columns on /rose/ and the contact
     form leave free. Every reveal below restates transform without a scale,
     which returns the turntable to full size as the deck slides out. */
  transform: translateX(2.09rem) scale(.652);
}

.qb-player__record:focus-visible,
.qb-player[data-qb-player-state="expanded"] .qb-player__record {
  --qb-deck-reveal: 1;
  transform: translateX(-.7rem);
}

.qb-player__deck {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: inherit;
}

/* The chassis lives on a fading layer so the docked rest state can show the
   bare disc with no truncated rectangle behind it. */
.qb-player__deck::before {
  position: absolute;
  inset: 0;
  border: 1px solid color-mix(in srgb, white 28%, transparent);
  border-radius: inherit;
  background:
    linear-gradient(145deg, color-mix(in srgb, white 18%, transparent), transparent 38%),
    linear-gradient(160deg, #424943, #1b211c 72%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, white 45%, transparent),
    inset 0 -1px 0 color-mix(in srgb, black 55%, transparent),
    0 .7rem 1.8rem color-mix(in srgb, #000 38%, transparent);
  content: "";
  opacity: var(--qb-deck-reveal);
}

.qb-player__deck::after {
  position: absolute;
  right: .65rem;
  bottom: .55rem;
  width: .32rem;
  height: .32rem;
  border-radius: 50%;
  background: #d2352c;
  box-shadow: 0 0 0 2px color-mix(in srgb, #d2352c 24%, transparent);
  content: "";
  opacity: var(--qb-deck-reveal);
}

.qb-player__disc {
  position: absolute;
  top: .55rem;
  left: .55rem;
  display: grid;
  width: 4.6rem;
  height: 4.6rem;
  place-items: center;
  border: .16rem solid color-mix(in srgb, white 16%, #111411);
  border-radius: 50%;
  background:
    radial-gradient(circle at center, #d2352c 0 12%, #ece1c9 12.5% 14.5%, transparent 15%),
    repeating-radial-gradient(circle at center, #1b1c1a 0 1.5px, #070807 2px 3.5px);
  box-shadow:
    inset .3rem .18rem .7rem color-mix(in srgb, white 10%, transparent),
    0 .18rem .5rem color-mix(in srgb, #000 65%, transparent);
}

.qb-player__disc::after {
  position: absolute;
  width: .16rem;
  height: .16rem;
  border-radius: 50%;
  background: #d8ddd8;
  box-shadow: 0 0 0 1px #070807;
  content: "";
}

/* The record label names the side that is up: A is the recording, B the
   generated side, which wears celadon so the two never read alike. */
.qb-player__label {
  display: grid;
  width: 1.1rem;
  height: 1.1rem;
  place-items: center;
  color: #f5f3ea;
  font-family: var(--font-mono, "IBM Plex Mono", monospace);
  font-size: .5rem;
  font-weight: 700;
  letter-spacing: .02em;
}

.qb-player[data-qb-side="b"] .qb-player__label {
  color: #a9bfad;
}

.qb-player__tonearm {
  position: absolute;
  top: .72rem;
  right: .78rem;
  opacity: var(--qb-deck-reveal);
  width: .76rem;
  height: .76rem;
  border: 1px solid color-mix(in srgb, white 30%, transparent);
  border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #e7ebe6, #737b74 38%, #202620 70%);
  box-shadow: 0 .2rem .45rem color-mix(in srgb, #000 52%, transparent);
}

.qb-player__tonearm::before {
  position: absolute;
  top: .48rem;
  left: .29rem;
  width: .16rem;
  height: 3.2rem;
  border-radius: 999px;
  background: linear-gradient(90deg, #606861, #edf0eb 48%, #656d66);
  box-shadow: .08rem .1rem .18rem color-mix(in srgb, #000 52%, transparent);
  content: "";
  transform: rotate(24deg);
  transform-origin: top center;
}

.qb-player__tonearm::after {
  position: absolute;
  top: 3.35rem;
  left: -1rem;
  width: .56rem;
  height: .32rem;
  border-radius: .1rem;
  background: linear-gradient(135deg, #b9beb9, #303630 65%);
  box-shadow: 0 .12rem .2rem color-mix(in srgb, #000 52%, transparent);
  content: "";
  transform: rotate(24deg);
}

.qb-player__panel {
  position: absolute;
  top: 50%;
  right: 8.35rem;
  width: min(17.25rem, calc(100vw - 9.4rem));
  padding: 1rem;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, white 34%, transparent);
  border-radius: 1rem;
  background:
    linear-gradient(145deg, color-mix(in srgb, white 16%, transparent), transparent 42%),
    var(--qb-player-glass);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, white 46%, transparent),
    inset 0 -1px 0 color-mix(in srgb, #000 28%, transparent),
    0 1.1rem 2.8rem color-mix(in srgb, #000 38%, transparent);
  backdrop-filter: blur(30px) saturate(1.55);
  -webkit-backdrop-filter: blur(30px) saturate(1.55);
  transform: translateY(-50%);
}

.qb-player__panel::before {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(95% 58% at 18% 0%, color-mix(in srgb, white 17%, transparent), transparent 64%);
  pointer-events: none;
  content: "";
}

.qb-player__panel > * {
  position: relative;
}

.qb-player__panel[hidden] {
  display: none;
}

.qb-player__heading,
.qb-player__credits {
  margin: 0;
}

.qb-player__heading {
  color: #d8d4c8;
  font-family: var(--font-mono, "IBM Plex Mono", monospace);
  font-size: .65rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.qb-player__title,
.qb-player__creator,
.qb-player__status {
  display: block;
}

.qb-player__title {
  margin-top: .38rem;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.01em;
}

.qb-player__creator {
  color: #e3dfd3;
  font-size: .76rem;
}

.qb-player__status {
  min-height: 1.1em;
  margin-top: .34rem;
  color: #c9c5ba;
  font-family: var(--font-mono, "IBM Plex Mono", monospace);
  font-size: .67rem;
  letter-spacing: .03em;
}

/* Liner notes. The record's own waveform, decoded from the track on the
   first expand, is drawn on a canvas under the native range input, which
   stays the accessible scrubber: pointer, drag, arrow keys and the slider
   role all belong to the input. While the notes are pending or drawn the
   input is glass over the drawing and the canvas paints the playhead where
   the thumb stands; if the decode fails the canvas stands down and the input
   keeps its own track and thumb. The played bars are the panel's ink, the
   rest celadon, the playhead cinnabar; a room may retune the three tokens. */
.qb-player {
  --qb-wave-played: #f5f3ea;
  --qb-wave-rest: rgba(169, 191, 173, .85);
  --qb-wave-head: #d2352c;
}

.qb-player__scrub {
  position: relative;
  height: 2.6rem;
  margin: .72rem 0 .3rem;
}

.qb-player__wave {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: .35rem;
}

.qb-player__scrub[data-qb-wave="fallback"] .qb-player__wave {
  display: none;
}

.qb-player__times {
  display: flex;
  justify-content: space-between;
  margin: 0 0 .55rem;
  color: #c9c5ba;
  font-family: var(--font-mono, "IBM Plex Mono", monospace);
  font-size: .65rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: .03em;
}

.qb-player__progress {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1rem;
  margin: 0;
  appearance: none;
  background: transparent;
  cursor: pointer;
  transform: translateY(-50%);
}

.qb-player__scrub:not([data-qb-wave="fallback"]) .qb-player__progress {
  top: 0;
  height: 100%;
  border-radius: .35rem;
  transform: none;
}

.qb-player__scrub:not([data-qb-wave="fallback"]) .qb-player__progress::-webkit-slider-runnable-track {
  height: 100%;
  background: transparent;
  box-shadow: none;
}

.qb-player__scrub:not([data-qb-wave="fallback"]) .qb-player__progress::-webkit-slider-thumb {
  margin-top: 0;
  opacity: 0;
}

.qb-player__scrub:not([data-qb-wave="fallback"]) .qb-player__progress::-moz-range-track {
  height: 100%;
  background: transparent;
}

.qb-player__scrub:not([data-qb-wave="fallback"]) .qb-player__progress::-moz-range-thumb {
  opacity: 0;
}

.qb-player__progress::-webkit-slider-runnable-track {
  height: .25rem;
  border-radius: 999px;
  background: color-mix(in srgb, white 68%, transparent);
  box-shadow: inset 0 1px 2px color-mix(in srgb, #000 32%, transparent);
}

.qb-player__progress::-webkit-slider-thumb {
  width: .9rem;
  height: .9rem;
  margin-top: -.325rem;
  appearance: none;
  border: 2px solid color-mix(in srgb, white 28%, transparent);
  border-radius: 50%;
  background: #d2352c;
  box-shadow: 0 .18rem .38rem color-mix(in srgb, #000 45%, transparent);
}

.qb-player__progress::-moz-range-track {
  height: .25rem;
  border-radius: 999px;
  background: color-mix(in srgb, white 68%, transparent);
}

.qb-player__progress::-moz-range-thumb {
  width: .78rem;
  height: .78rem;
  border: 2px solid color-mix(in srgb, white 28%, transparent);
  border-radius: 50%;
  background: #d2352c;
}

/* The transport: Play takes the row, the flip sits beside it. The flip is
   not a transport control, it turns the record over to the generated
   B-side, so it keeps its own class. */
.qb-player__controls {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .38rem;
}

.qb-player__control,
.qb-player__flip,
.qb-player__hide,
.qb-player__restore {
  min-width: 44px;
  min-height: 44px;
  border: 0;
  color: inherit;
  background: var(--qb-player-glass-control);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, white 24%, transparent),
    inset 0 -1px 0 color-mix(in srgb, #000 18%, transparent);
  backdrop-filter: blur(14px) saturate(1.3);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  cursor: pointer;
}

.qb-player__control,
.qb-player__flip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: .45rem .7rem .45rem .55rem;
  border-radius: .65rem;
  font-size: .75rem;
  font-weight: 600;
}

.qb-player__control svg,
.qb-player__flip svg,
.qb-player__credits a svg {
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
}

.qb-player__control--primary {
  color: #171a17;
  background: color-mix(in srgb, #f5f3ea 94%, transparent);
  box-shadow:
    inset 0 1px 0 white,
    0 .2rem .55rem color-mix(in srgb, #000 18%, transparent);
  font-weight: 700;
}

.qb-player__credits {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .25rem;
  margin-top: .55rem;
  color: #d2cec3;
  font-size: .68rem;
}

.qb-player__credits[hidden] {
  display: none;
}

.qb-player__credits--b {
  line-height: 1.45;
}

.qb-player__credits a {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  min-height: 44px;
  padding-inline: .38rem;
  border-radius: .45rem;
  color: #fffdf4;
  background: color-mix(in srgb, white 8%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}

.qb-player__hide {
  width: 100%;
  min-height: 40px;
  margin-top: .72rem;
  border-radius: .65rem;
  font-size: .74rem;
  font-weight: 600;
}

.qb-player__restore {
  display: none;
  width: 2.1rem;
  height: 4.5rem;
  min-width: 0;
  padding: .35rem;
  border-radius: .75rem 0 0 .75rem;
  color: #f5f3ea;
  background: color-mix(in srgb, #172019 82%, transparent);
  font-size: .65rem;
  letter-spacing: .08em;
  writing-mode: vertical-rl;
}

.qb-player[data-qb-player-state="hidden"] .qb-player__record {
  display: none;
}

.qb-player[data-qb-player-state="hidden"] .qb-player__restore {
  display: block;
}

.qb-player__record:focus-visible,
.qb-player :is(.qb-player__control, .qb-player__flip, .qb-player__hide, .qb-player__restore, .qb-player__credits a):focus-visible {
  outline: 3px solid #d2352c;
  outline-offset: 3px;
}

.qb-player__progress:focus-visible {
  outline: 3px solid #d2352c;
  outline-offset: 4px;
  border-radius: 999px;
}

@keyframes qb-record-spin {
  to {
    transform: rotate(1turn);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .qb-player[data-playing="true"] .qb-player__disc {
    animation: qb-record-spin 4s linear infinite;
  }

  .qb-player__record,
  .qb-player__control,
  .qb-player__flip,
  .qb-player__hide,
  .qb-player__restore {
    transition:
      color 160ms cubic-bezier(.23, 1, .32, 1),
      background-color 160ms cubic-bezier(.23, 1, .32, 1),
      transform 220ms cubic-bezier(.23, 1, .32, 1);
  }

  .qb-player__deck::before,
  .qb-player__deck::after,
  .qb-player__tonearm {
    transition: opacity 220ms cubic-bezier(.23, 1, .32, 1);
  }
}

/* The slide-out is a state change, not decoration, so it stays available under
   reduced motion; only its transition is gated above. */
@media (hover: hover) and (pointer: fine) {
  .qb-player__record:hover {
    --qb-deck-reveal: 1;
    transform: translateX(-.7rem);
  }
}

@media (hover: hover) and (pointer: fine) {
  .qb-player__control:hover,
  .qb-player__flip:hover,
  .qb-player__hide:hover,
  .qb-player__restore:hover {
    background: color-mix(in srgb, white 20%, transparent);
  }
}

@media (prefers-reduced-transparency: reduce) {
  .qb-player__panel,
  .qb-player__restore {
    background: #1c251e;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .qb-player__control,
  .qb-player__flip,
  .qb-player__hide {
    background: #343d35;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

@media (prefers-contrast: more) {
  .qb-player__panel {
    border-color: #f5f3ea;
    background: #111712;
  }
}

@media (max-width: 44rem) {
  /* The dock is where the disc sits above the floor; the reserve is the room
     the page owes it, measured from the floor to the top of the disc plus
     1rem of ground above it. The record box is 5rem tall and the vinyl stops
     .52rem above its own floor. */
  body {
    --qb-player-dock: max(1rem, env(safe-area-inset-bottom, 0px));
    --qb-player-reserve: calc(var(--qb-player-dock) + 4.52rem + 1rem);
  }

  /* The dock only has to clear the back-to-top control on routes that carry
     the shared chrome. The homepage has none, so it keeps the corner. */
  body:has(.qb-chrome) {
    --qb-player-dock: calc(max(1rem, env(safe-area-inset-bottom, 0px)) + var(--qb-chrome-size) + .75rem);
  }

  .qb-player {
    top: auto;
    right: max(0px, env(safe-area-inset-right, 0px));
    bottom: var(--qb-player-dock);
    transform: none;
  }

  /* A fixed disc lands on whatever the page ends with, so the page's closing
     block reserves the height the resting disc occupies, the same way the
     header reserves inline pixels for the back button above.

     Which block closes the page differs by route. On the homepage it is the
     地杆's mount, not the footer: the roller hangs after </footer> closes, and
     its bottom padding is already the bare ground a hung scroll has under its
     rod, so the reserve simply lengthens that air and the disc floats in it.
     Padding the footer there would push the copy up and leave the disc on the
     rod. Everywhere else the footer closes the page, or <main> does on the
     routes that carry neither. */
  body:has(.qb-player) .roller-mount,
  body:has(.qb-player):not(:has(.roller-mount)) footer:last-of-type,
  body:has(.qb-player):not(:has(.roller-mount)):not(:has(footer)) main:last-of-type {
    padding-bottom: var(--qb-player-reserve);
  }

  /* On a phone the rest state is the same full floating disc, sized down for
     the smaller room; the chassis only materializes when the player is open
     or keyboard-focused. */
  .qb-player__record {
    width: 6.2rem;
    height: 5rem;
    transform: translateX(1.12rem);
  }

  .qb-player__record:focus-visible,
  .qb-player[data-qb-player-state="expanded"] .qb-player__record {
    transform: translateX(-.5rem);
  }

  .qb-player__disc {
    top: .48rem;
    left: .48rem;
    width: 4rem;
    height: 4rem;
  }

  .qb-player__tonearm {
    right: .62rem;
  }

  .qb-player__panel {
    top: auto;
    right: 6.9rem;
    bottom: 0;
    width: min(17.5rem, calc(100vw - 7.4rem));
    transform: none;
  }

  /* Reading pages keep the listener with the opening controls, so it scrolls
     away before the visitor reaches the text and icon category counts. */
  body:is(.rose-page, .icons-page) {
    position: relative;
    --qb-player-reserve: 0px;
  }

  body:is(.rose-page, .icons-page) .qb-chrome {
    position: static;
  }

  body:is(.rose-page, .icons-page) .qb-chrome__back {
    position: absolute;
  }

  body:is(.rose-page, .icons-page) .qb-chrome__top {
    position: relative;
    inset: auto;
    margin: 0 var(--qb-page-gutter) var(--space-6, 32px) auto;
  }

  body:is(.rose-page, .icons-page) .qb-player {
    position: absolute;
    top: max(1rem, env(safe-area-inset-top, 0px));
    right: max(1.5rem, env(safe-area-inset-right, 0px));
    bottom: auto;
  }

  body:is(.rose-page, .icons-page) .qb-player__panel {
    top: calc(100% + .5rem);
    right: 0;
    bottom: auto;
    width: min(17.5rem, calc(100vw - 3rem));
  }
}
