/*
 * Firefighter Pfister — story page
 *
 * Covers the article layout, the audio player, the Previous/Next buttons and
 * the All Stories drawer.
 */

.story-body {
  display: flex;
  justify-content: center;
  width: 100%;
  padding-block: 40px var(--space-2xl);
}

@media (min-width: 1000px) {
  .story-body {
    padding-block: 56px var(--space-2xl);
  }
}

.story {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  width: 100%;
  max-width: var(--layout-container);
  padding-inline: var(--layout-gutter);
}

@media (min-width: 1000px) {
  .story {
    gap: var(--space-lg);
  }
}

.story__prose {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ---------------------------------------------------------------- *
 * Audio player
 * ---------------------------------------------------------------- */

.player {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  /* No container background or border — the waveform is the whole object. */
}

.player__transport {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  width: 100%;
}

.player__play {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--accent-solid);
  color: var(--ash-900);
  cursor: pointer;
  transition: background-color 150ms ease;
}

.player__play:hover {
  background: var(--accent-hover);
}

.player__play svg {
  width: 18px;
  height: 20px;
}

.player__play .icon-pause,
.player[data-playing="true"] .player__play .icon-play {
  display: none;
}

.player[data-playing="true"] .player__play .icon-pause {
  display: block;
}

/*
 * The scrubber is a real <input type="range"> layered invisibly over the bars,
 * so keyboard and assistive tech get native seek behaviour and the bars stay
 * purely presentational.
 */
.player__scrub {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 40px;
}

.player__bars {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.player__bar {
  width: 3px;
  border-radius: 1.5px;
  background: var(--border-subtle);
  /* Height is set per-bar from the generated waveform data. */
  transition: background-color 90ms ease;
}

.player__bar[data-played="true"] {
  background: var(--accent-solid);
}

/*
 * Hover preview: everything up to the pointer dims toward the played colour,
 * so it is obvious the waveform is clickable and obvious where a click lands.
 * Distinct from the played state so the two never read as the same thing.
 */
.player__bar[data-preview="true"] {
  background: var(--border-strong);
}

.player__bar[data-preview="true"][data-played="true"] {
  background: var(--accent-hover);
}

@media (prefers-reduced-motion: reduce) {
  .player__bar {
    transition: none;
  }
}

/* Timestamp that follows the pointer, so the seek target is readable before
   committing to it. */
.player__tip {
  position: absolute;
  bottom: calc(100% + 6px);
  translate: -50% 0;
  padding: 3px 7px;
  border-radius: var(--radius-sm);
  background: var(--bg-inverse);
  color: var(--text-inverse);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease;
}

.player__scrub[data-hovering="true"] .player__tip {
  opacity: 1;
}

/* Pointer-driven affordances are meaningless on touch. */
@media (hover: none) {
  .player__tip {
    display: none;
  }
}

/* Mobile shows 48 of the 96 bars — every second value, same shape. */
@media (max-width: 767px) {
  .player__bar:nth-child(even) {
    display: none;
  }
}

.player__range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.player__range:focus-visible {
  opacity: 1;
  outline: 2px solid var(--accent-solid);
  outline-offset: 3px;
}

.player__volume {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 26px;
  height: 20px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-primary);
  cursor: pointer;
}

.player__volume svg {
  width: 26px;
  height: 20px;
}

.player__volume .icon-muted,
.player[data-muted="true"] .player__volume .icon-loud {
  display: none;
}

.player[data-muted="true"] .player__volume .icon-muted {
  display: block;
}

/* Insets match play button + gap on the left, volume + gap on the right, so
   the times align under the waveform only. */
.player__times {
  display: flex;
  justify-content: space-between;
  padding-inline: 76px 50px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- *
 * Previous / Next
 * ---------------------------------------------------------------- */

.story__pager {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  width: 100%;
  padding-top: var(--space-md);
}

.pager-btn {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1 1 0;
  padding: 16px 20px;
  border-radius: var(--radius-lg);
  background: var(--bg-inverse);
  text-decoration: none;
}

.pager-btn--prev {
  align-items: flex-start;
  text-align: left;
}

.pager-btn--next {
  align-items: flex-end;
  text-align: right;
}

.pager-btn__label {
  color: var(--accent-solid);
}

.pager-btn__title {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text-inverse);
}

/* Disabled is border-only with no fill. */
.pager-btn[aria-disabled="true"] {
  background: none;
  border: 2px solid var(--border-subtle);
  padding: 14px 18px;
  cursor: default;
}

.pager-btn[aria-disabled="true"] .pager-btn__title {
  color: var(--text-primary);
}

.pager-btn[aria-disabled="true"] .pager-btn__label {
  color: var(--text-eyebrow);
}

/*
 * Mobile and tablet show only "Previous" / "Next" in ember, no story titles.
 *
 * Same typography as the desktop title — Onest 700 at 19px — so the two read as
 * one component at different sizes. Without this it inherits the body serif at
 * weight 400 and looks like a different button entirely.
 */
.pager-btn__title--mobile {
  display: block;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
  /* Bone on the Ash fill, same as the desktop title — 17.86:1. Ember here
     would have been 2.07:1 against the page. */
  color: var(--text-inverse);
}

/* Disabled keeps the light border-only treatment, so the label sits on the
   page rather than on Ash. Smoke reads as unavailable and holds 5.23:1. */
.pager-btn[aria-disabled="true"] .pager-btn__title--mobile {
  color: var(--text-secondary);
}

/*
 * The compact button keeps the desktop fill — Ash ground, Bone label — and only
 * drops the eyebrow and story title. Leaving it border-only made the enabled
 * and disabled states pixel-identical here, since disabled is border-only too.
 */
@media (max-width: 999px) {
  .pager-btn {
    align-items: center;
    text-align: center;
  }

  .pager-btn__label,
  .pager-btn__title {
    display: none;
  }
}

@media (min-width: 1000px) {
  .pager-btn {
    flex: 0 1 auto;
    padding: 18px 30px;
  }

  .pager-btn[aria-disabled="true"] {
    padding: 16px 28px;
  }

  .pager-btn__title--mobile {
    display: none;
  }
}

/* ---------------------------------------------------------------- *
 * All Stories button + drawer
 * ---------------------------------------------------------------- */

.all-stories {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 11px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.1em;
  cursor: pointer;
  white-space: nowrap;
}

.all-stories__icon {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.all-stories__icon span {
  display: block;
  width: 11px;
  height: 1.4px;
  background: var(--accent-solid);
}

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgb(20 17 16 / 0.58);
  opacity: 0;
  visibility: hidden;
  transition: opacity 240ms ease, visibility 240ms;
}

.drawer {
  position: fixed;
  inset-block: 0;
  right: 0;
  z-index: 61;
  display: flex;
  flex-direction: column;
  width: min(468px, 100%);
  padding: 30px 36px 24px;
  background: var(--bg-page);
  box-shadow: -8px 0 32px rgb(0 0 0 / 0.24);
  transform: translateX(100%);
  transition: transform 260ms cubic-bezier(0.32, 0.72, 0, 1);
}

[data-drawer-open="true"] .drawer-scrim {
  opacity: 1;
  visibility: visible;
}

[data-drawer-open="true"] .drawer {
  transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
  .drawer,
  .drawer-scrim {
    transition: none;
  }
}

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

/*
 * The mockup sets this label in Ember/600 against the Smoke close control, so
 * the two read as heading and action. Ember on Bone is 2.87:1, so it takes
 * Ash/900 (17.86:1) instead — which keeps the pair distinct, where the shared
 * eyebrow colour would have flattened both to Smoke.
 */
.drawer__title {
  color: var(--text-primary);
}

.drawer__close {
  padding: 0 6px;
  border: 0;
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
}

.drawer__rule {
  flex-shrink: 0;
  height: 1px;
  margin: 0;
  border: 0;
  background: var(--accent-solid);
}

/* The list scrolls inside the panel; the head and rule stay put. */
.drawer__list {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
  margin: 0;
  padding: 14px 0 0;
}

.drawer__link {
  display: block;
  padding: 9px 0 9px 12px;
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-size: var(--type-small);
  font-weight: 500;
  line-height: 1.4;
  text-decoration: none;
  color: var(--text-primary);
}

.drawer__link:hover {
  background: var(--bg-raised);
}

/*
 * Current story: bold, with an ember ground rather than the mockup's Ember/600
 * text on Bone/200 — that pairing is 2.59:1, under the 4.5:1 that 16px needs.
 * Moving ember from the text to the fill keeps it unmistakably ember and lands
 * at 14.9:1. Approved 2026-08-22.
 */
.drawer__link[aria-current="page"] {
  background: var(--ember-100);
  font-weight: 700;
  color: var(--ash-900);
}

/* ---------------------------------------------------------------- *
 * Mature-audience marking
 * ---------------------------------------------------------------- */

/*
 * The badge is decorative on its own — "MA" means nothing read aloud — so every
 * use pairs it with .sr-only text. It is a <span>, not an image, so it scales
 * with the reader's font size instead of staying pinned when someone zooms.
 *
 * One geometry for all three uses: a 20px circle around 10px letters. Sizing it
 * in rem rather than em is the point — an em width resolves against the badge's
 * *own* font-size, so a 1.25em box around 0.8em text is a circle just 1.25x the
 * letter height. "MA" in Onest Bold runs about 1.5x its font-size wide, so it
 * spilled past the edges anywhere the badge inherited a live font-size. The
 * legend and the story notice hid that by overriding to a 10/20 pair; now every
 * instance is that pair, and it holds whatever context the badge sits in.
 */
.ma-badge {
  display: inline-grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 999px;
  background: var(--mature-ground);
  color: var(--mature-ink);
  font-family: var(--font-display);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  flex-shrink: 0;
  /*
   * Inline uses (the drawer) centre the circle on the optical middle of the
   * title rather than its baseline — a 20px disc hung off the baseline reads as
   * having fallen off the line. Ignored in the flex contexts, which centre on
   * their own.
   */
  vertical-align: 0.28em;
}

/* In the drawer the badge follows the title inline. */
.drawer__link .ma-badge {
  margin-left: 8px;
}

.drawer__legend {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding-top: 14px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--text-secondary);
}


/*
 * On the story page the notice sits between the title and the player. That
 * placement is the point: the audio is what most visitors actually consume, so
 * a warning below the transcript would arrive after they had pressed play.
 */
.story__mature {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.3;
  color: var(--mature-ground);
}

