/* HOME·DEEP (109) — "This week, in depth". (D-549)
 * SINGLE SOURCE: the .dpr-* prefix is styled ONLY here, imported by BOTH the WB card page
 * (workbench/home/deep-read.html) AND the app (web/index.html), so the two cannot drift
 * (card-dev mirror, check 16). Prefix: dpr.
 *
 * The card is the LAST module on home, and it is the only one that is not about her baby.
 * Everything above is "your week, your baby". This is the long read — the thing she puts on while
 * she is doing something else. So it is quieter than the cards above it: no mosaic, no rail, no
 * artwork. A title, a way in, and a way to listen.
 */

/* 🔴 THIS CARD IS NOT A CARD. THE SHELL ALREADY DREW ONE. (D-549i · holds D-435)
 *
 * Andrew: "why is this a card within a card (same in loading)".
 *
 * `.nh-mod` — the module wrapper the shell puts every home module in — ALREADY has the card
 * background, the 18px radius and the shadow. I gave `.dpr` the identical four properties, so the
 * app drew a card, and then drew the same card again inside it, 16px smaller.
 *
 * ⚠️ AND THE ANSWER WAS IN THE FILE NEXT DOOR THE WHOLE TIME. `.nh-mcard` — the collections slide —
 * has NO background, NO shadow, NO radius. Just padding. Because the shell owns the card chrome and
 * the CONTENT owns the content. D-435 says it in one line: ONE level of carding, no boxes nested
 * inside a card. I read that rule this morning, wrote a comment quoting it on another card, and
 * then built this one as a box inside a box.
 *
 * The module keeps the card. This keeps the padding. */
.dpr {
  padding: 0 var(--rhythm-inset);      /* .nh-mod already pads vertically (--rhythm-pad 0) */
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

.dpr-eyebrow {
  font-family: var(--font-label);
  font-size: var(--size-11);
  font-weight: var(--weight-700);
  letter-spacing: var(--tracking-05);
  text-transform: uppercase;
  /* ⚠️ GOLD, AND IT IS AN OPEN QUESTION, NOT A DECISION I GET TO MAKE.
   * This is the colour Andrew approved in the bake-off frame. It is `--kind-watch-icon` — the WATCH
   * family (D-454). But this card is not a watch, and it is not a read either: LISTENING IS NOT ONE
   * OF THE FOUR FAMILIES. read · do · watch · track has no room for a thing you hear.
   * D-440 permits gold as a NOTICE (never on an interactive control), and an eyebrow is not
   * interactive — so this is legal. It is also a fifth consumption mode wearing a fourth one's
   * colour, and that is a taxonomy decision for Andrew (D-431: never lock a colour off a widget). */
  color: var(--kind-watch-icon);
}
.dpr-title {
  font-family: var(--font-display);
  font-weight: var(--weight-500);
  font-size: var(--size-20);
  line-height: var(--leading-120);
  color: var(--text-primary);
}
/* .dpr-stand DELETED — Andrew: "forget the description, not needed." A class with no markup is a
 * rule that never fires, and a rule that never fires is a lie you will re-read in six months and
 * believe (D-522). */

/* ── 🔴 SEE ALL SITS TOP-RIGHT, ON THE EYEBROW'S LINE. (D-549i) ───────────────
 * Andrew: "put see all top right."
 * It was vertically centred against the whole meta block, so it floated beside the TITLE — which
 * made it look like a caption on the title rather than an action on the module. It belongs on the
 * eyebrow's baseline, opposite the label, exactly where every other home module puts its action
 * (the shell's own `.nh-mhead` does this: h2 left, action right, baseline-aligned). */
.dpr-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-12);
}
.dpr-eyerow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-8);
}
.dpr-play {
  width: var(--dim-56, 56px); height: var(--dim-56, 56px);   /* token-exception: the hero control */
  border-radius: var(--radius-round);
  border: 0;
  flex: none;
  background: var(--accent);
  color: var(--text-on-accent);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.dpr-play svg { width: var(--size-20); height: var(--size-20); display: block; }
.dpr-play:active { background: var(--accent-hover); }
.dpr-play:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
/* a play triangle is mathematically centred and LOOKS left — its mass sits left of its box (D-511) */
.dpr-ic-play { display: flex; margin-left: var(--nudge-2); }
.dpr-ic-pause { display: none; }
.dpr-playing .dpr-ic-play { display: none; }
.dpr-playing .dpr-ic-pause { display: flex; }

/* 🔴 THE TITLE AND THE CLOCK MUST NOT SHARE A LINE.
 *
 * They did. Both were inline spans in one column, so a long title ran STRAIGHT INTO the duration:
 * "Eyes finding hands3:38". Andrew: "the title cuts off the clip length."
 *
 * ⚠️ AND THAT IS NOT A SPACING BUG. Adding a margin would have hidden it for exactly as long as the
 * titles stayed short — the same trap as the collection tiles this morning, where the layout held
 * only because the content happened to fit. TWO UNRELATED THINGS WERE SHARING A LINE. The fix is
 * to stop them sharing it: the title owns the head row, the duration lives on the scrubber, beside
 * the thing it is a measurement OF. */
.dpr-meta { min-width: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.dpr-title { display: block; }

/* 🔴 THE CLOCK RIDES WITH THE WAVE. (D-549e — option A)
 * It used to sit bottom-left, on the same row as the read link, BECAUSE THAT IS WHERE THERE
 * HAPPENED TO BE ROOM once the transport moved to its own line. It was not near the wave it
 * measures, not near the button it qualifies, and it sat beside a link it has nothing to do with.
 * IT WAS NOT PLACED — IT WAS LEFT OVER. Andrew: "3:38 can't be where it is now."
 * Now it is one object with the waveform: this shape, this long. */
.dpr-waverow {
  display: flex;
  align-items: center;
  gap: var(--space-12);
}
.dpr-waverow .dpr-wave { flex: 1; width: auto; }
/* ── 🔴 THE SOUND WAVE. (D-549c) ─────────────────────────────────────────────
 * 56 bars, drawn from `peaks` — decoded from the real mp3 and STORED (never computed at render:
 * decodeAudioData needs the whole 3.5MB, so a live waveform is a card that stays blank until the
 * audio has downloaded).
 *
 * It is also the SCRUBBER — she taps it to seek. So it is not a picture, it is a control, and the
 * played portion is painted THROUGH the bars rather than over them: `.dpr-wplayed` is a coloured
 * block clipped to the bars' silhouette by `mix-blend-mode`, which means the wave keeps its shape
 * as it fills instead of being covered by a rectangle. */
/* ⚠️ `flex: 1` LIVED HERE AND MADE THE WAVE INVISIBLE. (D-549d)
 * The wave used to sit in a horizontal row (.dpr-scrub) beside the clock, where `flex: 1` meant
 * "take the leftover WIDTH". When the transport moved to its own row, the wave became a direct
 * child of the card — which is a flex COLUMN — and `flex: 1` now set the basis on the VERTICAL
 * axis: flex-basis 0 beat the explicit height, and the element collapsed to ZERO HEIGHT.
 *
 * It still rendered. It still measured 306px wide. Every bar was still in the DOM. It was simply
 * not there, and the only way to know was to look at the pixels — which is the entire argument for
 * checking the render instead of the markup. A rule that is correct in one container and silently
 * wrong in another is not a typo; it is a rule that never said which container it meant. */
.dpr-wave {
  position: relative;
  width: 100%;
  height: var(--dim-32);              /* enough to read a shape; not so tall it becomes furniture */
  cursor: pointer;
  overflow: hidden;
}
/* one row of bars. Rendered TWICE — once in cream, once in teal inside the clipped .dpr-wplayed. */
.dpr-wbars {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: 2px;                            /* token-exception: a hairline gutter between bars */
}
.dpr-wb {
  flex: 1;
  min-width: 0;
  border-radius: var(--radius-pill);
  background: var(--cream-500);
}

/* 🔴 THE PLAYED PORTION KEEPS THE WAVE'S SHAPE.
 * It is a CLIPPED COPY of the same bars, not a coloured block laid over them. My first version
 * blended a teal rectangle across the wave — which coloured the GAPS between the bars as well, so
 * the waveform turned into a solid teal slab exactly as it started to mean something. A progress
 * indicator that destroys the thing it indicates progress through is worse than none. */
.dpr-wplayed {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  overflow: hidden;                    /* the clip — this is the whole trick */
  transition: width var(--duration-200) linear;
  pointer-events: none;
}
.dpr-wplayed .dpr-wbars { width: var(--dpr-wave-w, 100%); }
.dpr-wplayed .dpr-wb { background: var(--accent); }
.dpr-wave:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.dpr-time {
  flex: none;
  font-family: var(--font-label);
  font-size: var(--size-12);
  font-weight: var(--weight-600);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;   /* the clock must not JITTER as its digits change */
}
.dpr-expand {
  width: var(--dim-32); height: var(--dim-32);
  flex: none;
  border: 0; background: 0;
  border-radius: var(--radius-round);
  color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.dpr-expand svg { width: var(--size-16); height: var(--size-16); display: block; }
.dpr-expand:active { opacity: 0.72; }
.dpr-expand:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* ── THE READ BUTTON — secondary now. (D-549b)
 * It was the primary action when the card led with the article. The card leads with the sound now,
 * so this is the quiet way out to the prose, not the headline act. */
.dpr-read {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  align-self: flex-start;
  min-height: var(--dim-44);              /* a thumb, not a cursor */
  padding: var(--space-8) var(--space-12);
  margin-left: calc(-1 * var(--space-12));
  background: 0;
  border: 0;
  border-radius: var(--radius-12);
  color: var(--accent);
  font-family: var(--font-label);
  font-size: var(--size-15);
  font-weight: var(--weight-600);
  cursor: pointer;
}
.dpr-read svg { width: var(--size-20); height: var(--size-20); display: block; flex: none; }
/* 🔴 THE GAP UNDER "READ THE ARTICLE" WAS DEAD SPACE INSIDE THE BUTTON, NOT A MARGIN. (D-549i)
 * Andrew: "this gap under Read looks big."
 * The control is 44px tall because a THUMB needs 44px — but its label is only ~20px, so ~12px of
 * that target hangs below the text as invisible padding, and then the module adds its own 16px
 * beneath. The eye reads 28px of nothing.
 * ⚠️ The fix is NOT to shrink the button: the touch target is the one number here that is about a
 * human being. So the target keeps its height and the BOX is pulled back optically — the dead space
 * overlaps the module's padding instead of stacking on top of it. */
.dpr-read { margin-bottom: calc(-1 * var(--space-8)); }
.dpr-read:active { background: var(--surface-card-hover); opacity: 0.72; }
.dpr-read:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* ⚠️ `.dpr-soon` / `.dpr-readonly` / `.dpr-noaudio` DELETED (D-549h).
 * Andrew: "we are doing a demo. no need for nothing written yet or not recorded."
 * No article, or no audio ⇒ the module is simply ABSENT (renderDeepRead returns null), the same
 * rule the collections and tools rails already follow. Their CSS went with them: a rule that never
 * fires is a lie you will re-read in six months and believe (D-522). */

/* loading — holds the module's place so it cannot pop in and shove the page (D-520). No shimmer. */
.dpr-sk { display: block; border-radius: var(--radius-4); background: var(--surface-sunken); }
.dpr-sk-eyebrow { width: 30%; height: var(--size-11); }
.dpr-sk-title   { width: 72%; height: var(--size-20); }
.dpr-sk-line    { width: 100%; height: var(--dim-44); border-radius: var(--radius-12); }

/* ── 🔴 THE TRANSPORT — 1× · −15 · play/pause · +30. (D-549d) ─────────────────
 * The podcast convention. The asymmetry is deliberate: BACK is for the sentence she missed (short),
 * FORWARD is for the bit she does not want (long). Play stays the biggest thing on the card. */
.dpr-transport {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-16);
}
.dpr-rate {
  min-width: var(--dim-40);
  height: var(--dim-32);
  padding: 0 var(--space-8);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-family: var(--font-label);
  font-size: var(--size-12);
  font-weight: var(--weight-700);
  font-variant-numeric: tabular-nums;   /* 1× → 1.25× must not shove the buttons sideways */
  cursor: pointer;
}
.dpr-rate:active { background: var(--cream-500); }
.dpr-rate:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.dpr-skip {
  width: var(--dim-40); height: var(--dim-40);
  flex: none;
  border: 0; background: 0;
  border-radius: var(--radius-round);
  color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.dpr-skip { position: relative; }
/* ⚠️ SCALED, NOT RESIZED. (D-549j — Andrew: "increase the size of the circular arrows very slightly")
 * `transform` paints OUTSIDE the layout box, so the glyph grows and the 40px touch target, the
 * 16px gaps and the centring of the whole transport row do not move a pixel. Growing width/height
 * instead would push the play button off-centre — which is exactly how the "bigger active icon"
 * silently grew the nav bar by 8px (D-522). The number is a separate span and is untouched. */
.dpr-skip svg { width: var(--size-24); height: var(--size-24); display: block; transform: scale(1.12); }
/* 🔴 THE NUMBER IS TEXT, NOT PART OF THE GLYPH. (D-549g)
 * I had baked "15" and "30" INSIDE the SVG, in `system-ui` — a font that appears nowhere else in
 * this app (D-429: Fraunces / Inter / Schibsted only), hidden in a place no linter would ever look.
 * Phosphor has no numbered-skip glyph, and inventing one is what got the icons looking wrong in the
 * first place. So the glyph stays a glyph, and the number is set in the label face, like every
 * other number here. */
.dpr-skipn {
  position: absolute;
  top: 52%;                            /* optical: the arrow's bowl sits low in its box */
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-label);
  font-size: var(--size-8);
  font-weight: var(--weight-700);
  color: currentColor;
  pointer-events: none;
}
.dpr-skip:active { opacity: 0.72; }
.dpr-skip:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* the foot — clock on the left, the quiet way out to the prose on the right */
.dpr-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); }

/* ── 🔴 THE CHEVRON ACTIONS. (D-453 — LOCKED APP-WIDE, and it is NOT the old ⋯) ─
 * The three-dots tested badly — "I didn't know what the 3 dots would do till I clicked." A caret is
 * a disclosure: it says there is more, in a direction. It rotates 90° when open, and the menu drops
 * DIRECTLY BENEATH IT, because the tap and the reveal have to happen in the same place. */
/* SEE ALL — the same control the other home modules use, so the back catalogue reads as a place
 * and not as a novelty. */
.dpr-seeall {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  min-height: var(--dim-32);
  padding: 0 var(--space-4);
  background: 0; border: 0;
  color: var(--accent);
  font-family: var(--font-label);
  font-size: var(--size-13);
  font-weight: var(--weight-600);
  cursor: pointer;
}
.dpr-seeall svg { width: var(--size-14); height: var(--size-14); display: block; }
.dpr-seeall:active { opacity: 0.72; }
.dpr-seeall:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* ⚠️ THE CHEVRON MENU AND THE ROUTE PICKER LEFT THIS CARD (D-549e) — AND SO HAVE THEIR RULES.
 *
 * They lived HERE, with a `dpr-` prefix, long after the menu itself had moved to /listen. Card 109's
 * stylesheet was the sole owner of a component card 109 DOES NOT RENDER, and the player was reaching
 * across into it. I had even written a comment saying the rules were "kept because the player reuses
 * them" — a confession dressed up as documentation.
 *
 * Locking 109 turned on the card-mirror check, which asks the question no human was asking: DOES
 * THIS CARD'S STYLESHEET ONLY STYLE THIS CARD? It did not. The menu is app-wide (D-453), so it is
 * now SHARED·ACTIONS (403) — web/css/cards/shared/actions.css, prefix `act-`. (D-556) */
