/* Journal Post (desktop) — full rebuild from
   figma.com/design/NmseLluZJR0NqBKcwIq02A, node 156:553
   ("Desktop-Journal Entry", "Journal-Landing" file). Replaces the
   entire previous collage-based build. See the HTML comment at the
   top of .jp-page's markup in journal-post.html for the full
   rationale (architecture, the background revision, the two remaining
   deliberate Figma omissions, and the photo-placeholder decision), and
   TODO.md, "Journal Post Desktop
   — Full rebuild from new Figma reference".

   Architecture: normal document flow throughout — no fixed-aspect
   "stage," no overflow:hidden clipping content, no
   absolute-position-everything. Only the small decorative header
   cluster (.jp-header: logo badge + nav) uses internal absolute
   positioning against its own auto-sized wrapper. Reference frame
   width (1492px) is still used for left/width percentages site-wide,
   same convention as every other page in this family
   (css/journal.css, the old .jp-stage).

   Background: a flat var(--color-paper) on .page-journal-post (the one
   sitewide paper color, #FFE6AC, Sarah, September 2026; this page used
   Figma's #fbe6b2 before) with one textured PNG (the red-stripe
   texture, .jp-header__stripe) behind .jp-nav, near the very top of
   the page, not a full-height tiled texture. See the HTML comment on
   .jp-header's markup and TODO.md for the history. */
.page-journal-post {
  background-color: var(--color-paper);
}

.page-journal-post main.journal-post-page {
  max-width: none;
  padding: 0;
}

/* No max-width here (unlike .jp-article further down, which deliberately
   caps at 1092px for readable line length): the header's red-stripe
   texture and logo badge are meant to bleed to both true viewport edges
   at any width, same fix already applied to the old Journal Post build
   and to the About page. Every child here is already percentage-based
   against this box's own width (left/width geometry, plus vw-based
   heights on the stripe), so removing the cap doesn't need new layout
   math — it was already built to scale to any width, just previously
   clamped at 1492px. Verified at 1440/1512/1920/2560px: no gutter,
   stripe/logo/all 5 nav tabs span genuinely edge-to-edge. */
.jp-page {
  width: 100%;
}

/* ── Header cluster (logo badge + red-stripe texture + nav) ──
   .jp-header is the shared positioning box for both .jp-header__decor
   (the purely ornamental stripe+logo) AND .jp-nav (real, functional
   navigation — deliberately NOT nested inside the aria-hidden decor
   div; see the HTML comment on .jp-header's markup). Their relationship
   to each other (logo overlapping the page's top-left corner, nav
   sitting to its right, both against a red-stripe backdrop) doesn't
   change with essay length, unlike the rest of the page below it.

   Sized via padding-top (a real, width-relative height — CSS resolves
   vertical padding percentages against the containing block's WIDTH,
   the same technique already used elsewhere in this file for
   margin-top) to the logo badge's own post-rotation bounding box,
   minus the 20px it starts above this container's own top edge (see
   .jp-logo-badge's top): 269.134/1492 = 18.0399%, rounded to 18.04%.
   `height: 0` alongside it is the standard aspect-ratio-box technique
   (the same one used for responsive video embeds long before the CSS
   `aspect-ratio` property existed), not redundant with padding-top:
   without it, this box's `height` computes to `auto` (padding alone
   doesn't count as an explicit height per spec), and BOTH bugs below
   trace back to that.

   Two real bugs found and fixed while verifying the red-stripe layer
   this task added (checked with exact getBoundingClientRect
   measurements, not just a visual screenshot, precisely because
   "nav sits cleanly on the stripe" needed to be actually true, not
   approximately true):
   1. .jp-nav was a DOM sibling of .jp-header, not a child — so it
      was never positioned relative to it at all. With no positioned
      ancestor, its containing block fell back to the initial
      containing block (the viewport), and its `top: 10.7734%`
      resolved against the viewport's height instead of this box's
      269.134px reference (measured: 129px from the top of a 1200px
      test viewport — 10.7734% of 1200 — instead of the intended 28px
      from a 259.766px-tall header). This had been silently wrong
      since the original full rebuild; it only surfaced now because
      this task required nav to sit within a precise 150px-tall stripe
      band rather than "somewhere near the top of a tall page," which
      a casual screenshot check doesn't catch. Fixed by moving <nav>
      to be a real child of .jp-header (see the HTML comment).
   2. Even after fixing that nesting, .jp-header's own `height: auto`
      (padding alone, no explicit `height`) would have left .jp-nav's
      percentages resolving against .jp-header's PARENT instead —
      fixed by the `height: 0` on this rule.
   isolation:isolate is scoped to .jp-header__decor now (not this
   outer box), containing just the stripe+logo's own internal
   stacking — see the comment there for why the previous, broader
   placement on this element was equivalent for two children but is
   now scoped correctly for three (decor + nav). */
.jp-header {
  position: relative;
  height: 0;
  padding-top: 18.04%;
  margin-bottom: 16px;
}

/* isolation:isolate contains this decorative cluster's own
   absolutely-positioned children (the red-stripe texture, the logo)
   to itself, so they never get compared against the unrelated
   positioned elements further down the page (polaroid cards,
   pull-quote, stars, and now also .jp-nav, a sibling rather than a
   descendant) in the same ambient stacking context — the exact bug
   this codebase hit repeatedly on the old .jp-stage (see TODO.md,
   "Journal Post — Page height capped at 1024px", bug #2) before
   isolation:isolate fixed it there; applied here from the start
   rather than waiting to hit it again. inset:0 makes this a plain
   full-cover child of the now-definite-height .jp-header, so its own
   children's top/height percentages resolve against that same
   269.134px reference. */
.jp-header__decor {
  position: absolute;
  inset: 0;
  isolation: isolate;
}

/* Red stripe (Figma "Texture / Red Stripe", 161:601) — the real asset,
   exported directly from Figma by Sarah (assets/images/journal/
   texture-red-stripe.png; the file already in the repo turned out to
   be byte-equivalent to her fresh export, confirmed by an alpha-channel
   diff against the torn-edge mask — both come from the same source).
   Same asset already used behind Journal Landing's nav (.jv2-bg-stripe
   in css/journal.css) — not a new export, and the same "nav sits on
   the stripe" relationship as that page.

   This is a `background-image` div, not an `<img>` with object-fit —
   deliberately, because object-fit:cover always maps the FULL 1856px
   source width to this element's own box width with no way to zoom
   past that, and this asset is a torn scrap with irregular edges on
   ALL FOUR sides (confirmed by a full per-row scan of the complete
   2250px height, not a handful of samples): no horizontal band is
   genuinely solid edge-to-edge at the full 1856px width. A first
   scan checked only the alpha channel and missed part of the problem
   — this asset's torn edge is frequently rendered as OPAQUE off-white/
   grey torn-paper fiber, not transparency, so it doesn't show up as a
   transparency hole at all; it has to be detected by color (the torn
   fiber is neutral/cool — red≈blue — while every genuine stripe pixel,
   cream or red, is warm, red visibly greater than blue). Re-scanning
   with that color test found the asset's actual best window at rows
   828–1078 (250px tall), needing a 114px margin trimmed off both the
   left and right before the remaining width is reliably solid at
   every row within it — confirmed both numerically (re-run at window
   sizes 200/220/250px, all agreeing to within a couple of px) and
   visually (the exact displayed crop extracted and viewed directly at
   all four widths this task tests, including zoomed-in crops of just
   the left/right 80px at each — not a full-page screenshot glance,
   which is what missed this the first time).

   `background-size` lets the image be scaled independently of this
   element's own box, so the unsafe margin can be zoomed past (cropped)
   while still filling the box exactly: sizing the image to 114.851%
   of this element's width (1856 / (1856 − 2×120) × 100, 120 rounding
   114 up for a small buffer) maps only the safe, verified-solid inner
   1616px of the source across this element's full width, with
   `background-position: center 42%` doing both the horizontal
   centering (the margins are symmetric) and picking the vertical
   offset that keeps the visible window inside 828–1078 at every
   tested width (877–1039px source rows at 1440, narrowing to
   905–1000px at 2560 as the effective zoom increases with viewport
   width — both comfortably inside the verified band).

   height/max-height (10vw / 150px) are unchanged from before — still
   what keeps this scaling with viewport width without exceeding
   .jp-nav's own footprint, per the earlier pass's own reasoning. */
.jp-header__stripe {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 10vw;
  max-height: 150px;
  background-image: url('/assets/images/journal/texture-red-stripe.png');
  background-size: 114.851% auto;
  background-position: center 42%;
  background-repeat: no-repeat;
  z-index: 0;
}

/* Logo badge (Figma "logo-badge-angled", 156:558) — unchanged geometry
   from the previous build (confirmed: same -34,-20,436.083,289.134
   outer box, same 404×166 natural inner size, same -19.11deg), only
   re-expressed against this header's own 269.134px reference height
   instead of the old 1024px stage. Same asset as before
   (home-logo-sharp.png — the approved gold wordmark, ASSET-MANIFEST.md),
   not a new export. */
.jp-logo-badge {
  position: absolute;
  left: -2.2788%;
  top: -7.431%;
  width: 29.2317%;
  height: 107.431%;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.jp-logo-badge__inner {
  width: 92.6449%;
  height: 57.4074%;
  transform: rotate(-19.11deg);
}

.jp-logo-badge__inner img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

/* Nav — unchanged geometry/asset from the previous build (Figma's own
   nav frame, x=592,y=29,w=814,h=57, is identical between the old and
   new "Desktop-Journal Entry" frames); only `top` is re-expressed
   against .jp-header's own 269.134px reference height (29/269.134 =
   10.7734%) instead of the old 1024px stage (where it was 2.832%).
   left/width are unchanged since both already resolve against the
   same 1492px reference width in both builds. */
.jp-nav {
  position: absolute;
  left: 39.6782%;
  top: 10.7734%;
  width: 54.5576%;
  z-index: 2;
}

.jp-nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 3.1941%;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The <li> is the actual flex item (not the <a>.jp-nav__tab it wraps),
   so the 142/814 width percentage is set here — sizing the <a> itself
   would resolve against the <li>'s own auto (shrink-wrapped) width,
   the same circular-reference problem noted above on .jp-nav. */
.jp-nav li {
  width: 17.4448%;
  aspect-ratio: 142 / 57;
}

.jp-nav__tab {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background-image: url('/assets/images/shared/nav-paper-tab.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  font-family: var(--font-display);
  font-size: clamp(0.9rem, 1.34vw, 1.25rem);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  color: var(--color-near-black);
}

.jp-nav__tab[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: var(--color-crimson);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.jp-nav__tab:hover {
  text-decoration: underline;
}

/* ── Title Block ── metadata top-right, title + underline centered
   below. Now a normal-flow block (a sibling of .jp-header, not an
   inset:0 absolute overlay on a fixed-height stage) — meta/meta-rule
   are the only children still absolutely positioned, pinned to the
   title block's own top-right corner, which is independent of essay
   length. left/width values are still the exact Figma percentages of
   the 1492px reference frame (metadata box resolved from Figma's
   center-anchored 1315.5/243 as left=1194,width=243; title similarly
   from 771.5/801 as left=371,width=801) — expressed here as `right`
   (measuring from the title block's own right edge, which is simpler
   than converting to a left+translateX given both boxes are already
   right-of-center) rather than `left`, and title is centered via
   margin:0 auto instead of Figma's precise (slightly off-center) left
   value: a deliberate simplification for this "much lighter" pass,
   not a precision loss anywhere that matters (a symmetric title reads
   as more intentional than a 25px-off-center one at this size). */
.jp-title-block {
  position: relative;
  padding: 8px 0 28px;
}

.jp-title-block__meta {
  position: absolute;
  top: 0;
  right: 3.6863%;
  width: 16.287%;
  margin: 0;
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(0.7rem, 0.87vw, 0.8125rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  color: var(--color-near-black);
}

.jp-title-block__meta-rule {
  position: absolute;
  top: 21px;
  right: 3.9544%;
  width: 16.4879%;
  height: 1px;
  background-color: var(--color-crimson);
}

/* Width constrains wrap only — height is intentionally not fixed so a
   real (longer) title can grow without being clipped or truncated. */
.jp-title-block__title {
  width: 53.6864%;
  max-width: 801px;
  margin: 40px auto 0;
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 6.7vw, 6.25rem);
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: center;
  color: var(--color-near-black);
}

/* Still a flat var(--color-crimson) bar, not Figma's real textured
   brush-stroke asset — that asset remains undownloadable in this
   sandbox (egress blocked to www.figma.com), same still-open item as
   before this rebuild. See TODO.md, "Journal Post — Title Block
   underline needs the real asset". */
.jp-title-block__rule {
  width: 43.0965%;
  max-width: 643px;
  height: 2px;
  margin: 16px auto 0;
  background-color: var(--color-crimson);
}

/* ── Article column ── the flowing content: hero, body copy, the two
   polaroids, and the pull-quote all live here as ordinary block-level
   siblings, in document order. Width matches Figma's hero-image/pull-
   quote-container width (1092/1492 = 73.1902%) — both of those blocks
   span the article's full width; body copy and the polaroids are
   deliberately narrower and centered within it (see their own rules
   below) for readability, a single-column simplification of Figma's
   original two-column layout (see the HTML comment on .jp-page's
   markup for the full reasoning). position:relative only so any
   future block could anchor a small decorative accent to the article
   itself if needed — nothing currently uses it. */
.jp-article {
  position: relative;
  width: 73.1902%;
  max-width: 1092px;
  margin: 0 auto;
}

/* ── Hero (content block 1, optional) ── Figma hero-image-container
   (164:4), 1092×420. No tape pieces (see the HTML comment on
   .jp-page's markup — this task's own content-block list doesn't
   include tape on the hero, unlike the two polaroids). The photo is the
   entry's CMS Hero Image, cropped to the frame. margin-bottom is this block's own
   spacing to whatever follows; when this block is absent, nothing
   else needs to change; since every block below is an ordinary flow
   sibling, the next one simply moves up to occupy the freed space. */
.jp-hero {
  margin: 0 0 32px;
}

.jp-hero__photo {
  display: block;
  width: 100%;
  object-fit: cover;
  aspect-ratio: 1092 / 420;
  border-radius: 3px;
  background-color: #d8c9a3;
  border: 1px solid rgba(28, 26, 22, 0.15);
}

.jp-hero__caption {
  margin: 10px 0 0;
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.8125rem;
  text-align: center;
  color: var(--color-near-black);
  opacity: 0.7;
}

/* ── Body copy (content blocks 2/4/6/8, required) ── Narrower than
   the article column and centered, for line-length readability — a
   plain paragraph group with no positioning of its own, so it always
   just flows to wherever the previous block (or the top of .jp-article,
   if nothing precedes it) ends. */
.jp-body-copy {
  max-width: 640px;
  margin: 0 auto 32px;
}

.jp-body-copy:last-child {
  margin-bottom: 0;
}

.jp-body-copy p {
  font-family: var(--font-body);
  font-size: clamp(1rem, 1.34vw, 1.25rem);
  margin: 0 0 1.5em;
}

.jp-body-copy p:last-child {
  margin-bottom: 0;
}

/* Hero Image position (CMS "Image position" field): which part of the
   photo stays visible when object-fit: cover crops it. Also applied to
   the mobile polaroid hero. */
.jp-photo--top { object-position: center top; }
.jp-photo--center { object-position: center center; }
.jp-photo--bottom { object-position: center bottom; }

/* ── Polaroids (content blocks 3/7, optional) ── Each is a centered
   card: real tape + photo + caption elements, not one flattened
   image, so a real essay only ever needs to swap the photo (this is
   what resolves TODO.md's "Journal Post — Hero photo needs to become
   swappable" item — see the entry marked resolved there). Rotation
   differs between the two per this task's explicit instruction
   (+3deg / -2.5deg, matching Figma's polaroid-1/polaroid-2 exactly).
   Sizes (300px / 340px, and each photo's own aspect-ratio) are
   Figma's own box dimensions for 164:12/164:24. */
.jp-polaroid {
  display: flex;
  justify-content: center;
  margin: 0 0 32px;
}

.jp-polaroid__card {
  position: relative;
  background-color: #fefcf5;
  border-radius: 2px;
  padding: 16px 16px 18px;
  box-shadow: 4px 6px 6px rgba(0, 0, 0, 0.18);
}

.jp-polaroid--1 .jp-polaroid__card {
  width: 300px;
  transform: rotate(3deg);
}

.jp-polaroid--2 .jp-polaroid__card {
  width: 340px;
  transform: rotate(-2.5deg);
}

.jp-polaroid__photo {
  display: block;
  width: 100%;
  object-fit: cover;
  border: 1px solid rgba(28, 26, 22, 0.15);
  background-color: #d8c9a3;
}

.jp-polaroid--1 .jp-polaroid__photo {
  aspect-ratio: 279.57 / 241.71;
}

.jp-polaroid--2 .jp-polaroid__photo {
  aspect-ratio: 319.14 / 275.19;
}

.jp-polaroid__caption {
  margin: 10px 0 0;
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.8125rem;
  text-align: center;
  color: var(--color-near-black);
  opacity: 0.75;
}

.jp-polaroid__tape {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  width: 100px;
  height: auto;
  max-width: none;
  object-fit: contain;
  pointer-events: none;
}

.jp-polaroid--2 .jp-polaroid__tape {
  width: 120px;
}

/* Two kept scribble-star accents (see the HTML comment on .jp-page's
   markup for why only two of Figma's three star instances are built)
   — each scoped to its own polaroid card as a small corner flourish,
   so it only ever appears together with that polaroid and never as an
   orphaned decoration when the card is absent. */
.jp-decor__star {
  position: absolute;
  width: 36px;
  height: 36px;
  max-width: none;
  pointer-events: none;
}

.jp-decor__star--1 {
  top: -20px;
  right: -20px;
}

.jp-decor__star--2 {
  bottom: -16px;
  left: -18px;
  transform: scaleY(-1);
}

/* ── Pull-quote (content block 5, optional) ── Figma
   pull-quote-container (164:17), full article width, exact
   background color match (--color-crimson === Figma's #af3838). No
   tape (see the HTML comment on .jp-page's markup). The megaphone
   decal is scoped to this block the same way the stars are scoped to
   their polaroids — appears only alongside the pull-quote, never
   orphaned. */
.jp-pull-quote {
  position: relative;
  margin: 0 0 32px;
  padding: 44px 64px;
  background-color: var(--color-crimson);
  border-radius: 2px;
  text-align: center;
}

.jp-pull-quote__mark {
  position: absolute;
  font-family: var(--font-body);
  font-size: 4.5rem;
  line-height: 1;
  color: #fefcf5;
  opacity: 0.4;
}

.jp-pull-quote__mark--open {
  top: 8px;
  left: 24px;
}

.jp-pull-quote__mark--close {
  bottom: -4px;
  right: 24px;
}

.jp-pull-quote__text {
  margin: 0;
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(1.125rem, 1.7vw, 1.625rem);
  line-height: 1.4;
  color: #fefcf5;
}

.jp-decor__megaphone {
  position: absolute;
  bottom: -24px;
  right: -16px;
  width: 90px;
  height: auto;
  max-width: none;
  object-fit: contain;
  pointer-events: none;
  transform: rotate(-14deg);
}

/* ══════════════════════════════════════════════════════════════════
   Mobile Journal Post (390px reference frame, Figma node 55:4
   "mobile-journal-entry") — Header only, this pass.

   STANDING RULE FOR EVERY SECTION ADDED TO THIS PAGE (Nav,
   Title Block, Polaroid Hero, Essay Body, Collage Footer): .jpm-page
   must NEVER get a fixed height, `aspect-ratio`, or `overflow: hidden`
   sized to Figma's 2095px mobile frame height. Essay length varies per
   post, so the page's real height has to be driven by its own flow
   content, growing and scrolling normally to fit whatever a given
   essay actually needs — exactly what .jpm-page already does below
   (`display: block`, no height/aspect-ratio of its own) and verified
   by literally testing it: with only this Header built, scrollHeight
   is exactly the viewport (nothing forcing extra height); with a
   40-paragraph simulated essay injected after it, .jpm-page's own box
   grew to match that content's real height pixel-for-pixel, with the
   Header untouched. This is a deliberate contrast with desktop's
   .jp-stage, which used a fixed `aspect-ratio` copied from Figma's
   frame and had to be substantially reworked afterward once real
   body copy needed more room than the placeholder (see TODO.md,
   "Journal Post — Page height capped at 1024px..."). Any full-page
   background/texture layer added for this mobile page (matching
   desktop's 2:73/2:78, or Figma's own top-level "background-texture"
   node 55:5) must size itself to `.jpm-page`'s real, current height
   (e.g. `height: 100%` of a natural-height ancestor, never a literal
   `2095px`), and any element meant to anchor near the bottom of the
   design (e.g. CollageFooter's "Read something new!" sticker) must
   anchor relative to the actual end of content, never a hardcoded
   y-offset assuming Figma's exact frame height. Confirm each with the
   same two-pass test used here — the current placeholder length, and
   a simulated much-longer paragraph set — before considering that
   section done, not as a cleanup pass afterward.

   Same established pattern as Journal Landing's .jv2m-page (see
   journal.css): a real, independent mobile composition — not desktop
   scaled down — hidden by default and only shown under the mobile
   breakpoint, with .jp-stage (desktop) hidden in that same breakpoint
   so the two never render together. Sizes/spacing below are Figma's
   own literal px values (this is a scrolling flow page, not a
   fixed-aspect stage, so static px is the right technique here, same
   as Journal Landing's mobile page).

   Header padding (pt:24, px:16, pb:8) comes directly from Figma's own
   auto-layout properties on node 55:6, not a guess: 24 + 110.4263
   (logo's post-rotation height) + 8 = 142.4263 — matches the header
   frame's own stated height (142.4263153076172) essentially exactly,
   confirming these are the real values Figma renders with, not the
   raw metadata "absolute" y (36.56) for the logo child, which would
   leave the logo's rotated bounding box bleeding ~4.6px past the
   header's own bottom edge — inconsistent, and not what auto-layout
   would actually produce. Horizontal centering uses flexbox
   (align-items:center) rather than a computed left-offset: Figma's
   72.6px margins on both sides work out to exactly (390-244.8)/2,
   confirming the logo is centered, but flexbox centering is used here
   instead since it holds up correctly across viewport widths other
   than exactly 390px, per the task's explicit ask, without needing a
   separate computed value.

   Rotation: get_design_context on 55:6 shows the logo rotated -3deg
   ("-rotate-3") — the task brief's assumption of no rotation was
   wrong; confirmed directly against Figma rather than assumed, and
   cross-checked mathematically (a 240×98 rectangle rotated 3° yields
   a ~244.8×110.43px bounding box, matching node 55:7's own stated
   post-rotation size exactly). Uses the same flex-center-then-rotate
   technique already established sitewide (outer wrapper sized to the
   post-rotation bounding box, centering an inner element at the
   natural pre-rotation size, which carries the rotate() transform)
   rather than a naive transform-origin, avoiding the top-left-pivot
   issue documented elsewhere on this page.

   Asset: assets/images/home-v2/home-logo-sharp.png — the same
   approved gold wordmark already used on desktop (ASSET-MANIFEST.md),
   reused as-is, not re-exported. ══════════════════════════════════ */

.jpm-page {
  display: none;
}

@media (max-width: 599px) {
  .jp-page {
    display: none;
  }

  /* Page-level background texture — Figma node 55:5 ("background-texture"),
     a sibling of Header/Nav/etc. at the mobile-journal-entry frame level,
     confirmed (via grep across the codebase) to have never been added
     since Header first flagged it out of scope.

     Confirmed directly from Figma rather than guessed: get_metadata on
     55:5 gives a 390×2095 box (Figma's literal mobile frame size), and
     get_design_context composes it as a single `object-fit: cover`
     <img> — not a `background-repeat` tile — so this is one stretched
     texture meant to cover the frame, not a repeating pattern. Its
     screenshot (a deckled torn edge near the top ~20% down, plain paper
     grain with a faint diagonal crease below) is a close visual match
     for assets/images/listen/sarahtonin_sounds-background_paper_2_1.png
     — already the exact asset desktop's Journal Post uses for this same
     background-paper role (`.jp-decor__bg-base`, Figma node 2:73) — so
     that's reused here rather than exporting a new file.

     Applied as a CSS background-image on .jpm-page itself (not an
     absolutely-positioned <img>), using the same background-size:cover
     technique already shipped for this exact category of problem on
     Journal Landing's mobile page (.jv2m-page in journal.css): because
     .jpm-page's height is content-driven (the standing rule — see the
     comment above .jpm-page below) rather than a fixed px value,
     background-size:cover recomputes against the box's real current
     height on every layout, so it keeps covering the page automatically
     however tall a given essay makes it — confirmed with both the
     current placeholder length and a simulated much-longer essay (see
     verification notes for this task), not just reasoned about. */
  .jpm-page {
    display: block;
    width: 100%;
    max-width: 390px;
    margin: 0 auto;
    background-color: var(--color-cream);
    background-image: url('/assets/images/journal/post-mobile-paper-tinted.png');
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
  }

  .jpm-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 24px 16px 8px;
  }

  .jpm-header__logo {
    width: 244.8px;
    height: 110.4263px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .jpm-header__logo-inner {
    width: 240px;
    height: 98px;
    transform: rotate(-3deg);
  }

  .jpm-header__logo-inner img {
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: cover;
  }

  /* ── Nav ── Figma node 55:8 ("TapesNavigation"), a HORIZONTAL
     auto-layout frame with layoutWrap:WRAP, itemSpacing:8,
     counterAxisSpacing:8, padding 16px horizontal/12px vertical —
     replicated as plain flex-wrap, not two hardcoded row containers.
     The 3-top/2-bottom split is a natural consequence of each tab's
     own (rotated) width plus the 8px gaps not leaving room for a 4th
     item per row inside the 390-32=358px available width, confirmed
     by computing it directly: Home+About+Listen = 349.33px (fits in
     358), adding Journal next would need 469.49px (doesn't fit, so it
     wraps) — Journal+Contact then reflow onto their own row and get
     centered there too, same justify-content:center Figma uses. */
  .jpm-nav__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-start;
    gap: 8px;
    margin: 0;
    padding: 12px 16px;
    list-style: none;
  }

  /* Each <li> is sized to its tab's own POST-rotation bounding box
     (computed from a plain 110×44 rect at that tab's confirmed
     angle — see the HTML comment above this nav's markup for the
     exact math) so flex-wrap sees the same per-item footprint Figma's
     auto-layout does, including the extra room rotation adds. The
     <a> inside stays a plain, unrotated 110×44 box, flex-centered
     within that larger footprint, then carries its own rotation —
     the same flex-center-then-rotate technique used everywhere else
     on this site, so each tab rotates around its own center rather
     than a corner. */
  .jpm-nav__item {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }

  .jpm-nav__item--home { width: 111.469px; height: 47.812px; }
  .jpm-nav__item--about { width: 111.114px; height: 46.864px; }
  .jpm-nav__item--listen { width: 110.751px; height: 45.913px; }
  .jpm-nav__item--journal { width: 112.152px; height: 49.697px; }
  .jpm-nav__item--contact { width: 111.114px; height: 46.864px; }

  .jpm-nav__tab {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 110px;
    height: 44px;
    background-image: url('/assets/images/shared/nav-paper-tab.png');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    font-family: var(--font-display);
    font-size: 15px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    text-decoration: none;
    text-align: center;
    color: var(--color-near-black);
  }

  .jpm-nav__item--home .jpm-nav__tab { transform: rotate(-2deg); }
  .jpm-nav__item--about .jpm-nav__tab { transform: rotate(1.5deg); }
  .jpm-nav__item--listen .jpm-nav__tab { transform: rotate(-1deg); }
  .jpm-nav__item--journal .jpm-nav__tab { transform: rotate(3deg); }
  .jpm-nav__item--contact .jpm-nav__tab { transform: rotate(-1.5deg); }

  .jpm-nav__tab[aria-current="page"] {
    text-decoration: underline;
    text-decoration-color: var(--color-crimson);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
  }

  .jpm-nav__tab:hover {
    text-decoration: underline;
  }

  /* ── Title Block ── Figma node 55:19 ("PageTitleBlock"). Literal
     Figma px throughout, matching this page's established mobile
     technique (scrolling flow, not a fixed-aspect stage). Font
     substitutions and the flat-CSS underline are documented in the
     HTML comment above this block's markup. 0° rotation, matching the
     source frame. */
  .jpm-title-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 32px 24px 16px;
  }

  .jpm-title-block__meta {
    width: 100%;
    margin: 0;
    font-family: var(--font-body);
    font-style: italic;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    color: var(--color-near-black);
  }

  /* Not text-transform:uppercase, deliberately — see HTML comment. */
  .jpm-title-block__title {
    width: 100%;
    margin: 0;
    font-family: var(--font-display);
    font-size: 38px;
    line-height: 1.1;
    text-align: center;
    color: var(--color-near-black);
  }

  .jpm-title-block__rule {
    width: 220px;
    height: 2px;
    background-color: var(--color-crimson);
  }

  /* ── Polaroid Hero ── Figma node 55:23 ("PolaroidHero"). See the HTML
     comment above this section's markup for the full asset-reuse and
     no-extra-rotation rationale (mirrors desktop's Polaroid + Tape,
     94:14). Summary of the numbers used below:

     .jpm-polaroid is Figma's PolaroidFrame (260×330, rotate(-4deg))
     post-rotation bounding box: for a 260×330 rect rotated 4°,
     width = 260·cos4° + 330·sin4° = 282.386, height = 260·sin4° +
     330·cos4° = 347.333 — matches node 55:24's own stated wrapper size
     exactly, confirming the 4° magnitude.

     Rotation SIGN verified, not assumed: composing rotate(-4deg) on a
     rect's corner offsets from center — (x'=x·cosθ-y·sinθ,
     y'=x·sinθ+y·cosθ) — puts the top-right corner ~18px higher than the
     top-left corner. That's exactly the geometry measured directly off
     article-photo-sky-clouds.png's own alpha mask (topmost pixel at
     x=432/608 ≈ 71% across; leftmost pixel at y=117, noticeably lower)
     — so this file's already-baked tilt matches Figma's -4°, no flip
     needed here (unlike the Nav section's tab rotations elsewhere on
     this page, where the sign genuinely was flipped).

     .jpm-polaroid__tape's box/position is Figma's Orange-Tape
     (103.22×46.223, natural 100×26 rotated 12deg) composed through the
     frame's own -4° rotation (since Figma nests the tape inside the
     rotated PolaroidFrame, not as an independent sibling): the tape's
     local center offset from the frame's center, (-3.8, -155.89),
     rotated by -4° works out to (-14.67, -155.24) in the frame's
     post-rotation box — added to that box's own center (141.193,
     173.667) and re-anchored to a top-left origin gives left:74.916px;
     top:-4.688px. Net rotation this implies, -4°+12°=+8°, is in the
     same descending sense already measured in tape-orange.png's own
     baked-in ~-16° tilt (its alpha mask's leftmost pixel sits ~120px
     above its rightmost pixel), so — same reasoning as the photo above
     — no separate CSS rotate() is layered on top of it. */
  .jpm-polaroid-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 24px;
  }

  .jpm-polaroid {
    position: relative;
    width: 282.386px;
    height: 347.333px;
  }

  .jpm-polaroid__photo {
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: contain;
  }

  /* A CMS photo is a plain image with no baked-in frame or tilt (unlike
     the original article-photo-sky-clouds.png mock asset), so the frame
     is real markup: Figma's 260x330 PolaroidFrame at -4deg, centered in
     the 282x347 bounding box above, styled like desktop's
     .jp-polaroid__card. */
  .jpm-polaroid__frame {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 260px;
    height: 330px;
    margin: -165px 0 0 -130px;
    padding: 14px 14px 56px;
    box-sizing: border-box;
    background-color: #fefcf5;
    border-radius: 2px;
    box-shadow: 4px 6px 6px rgba(0, 0, 0, 0.18);
    transform: rotate(-4deg);
  }

  .jpm-polaroid__frame .jpm-polaroid__photo {
    object-fit: cover;
  }

  .jpm-polaroid__tape {
    position: absolute;
    left: 74.916px;
    top: -4.688px;
    width: 103.22px;
    height: 46.223px;
    max-width: none;
    object-fit: contain;
    pointer-events: none;
  }

  /* ── Essay Body ── Figma node 55:27 ("EssayBody"). See the HTML
     comment above this section's markup for the CMS/templating
     rationale and the divider's "optional, not fixed-midpoint" intent.
     gap:20px on the flex column applies uniformly between every pair
     of adjacent children — paragraph-to-paragraph, or
     paragraph-to-divider — so inserting/removing/moving the divider
     never requires touching this spacing. */
  .jpm-body-copy {
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 16px 24px 48px;
  }

  .jpm-body-copy p {
    margin: 0;
    font-family: var(--font-body);
    font-size: 17px;
  }

  /* Extra 12px top/bottom on top of the column's own 20px gap, matching
     Figma's py-[12px] on ScribbleDivider (55:29) — the star reads with
     more breathing room than a plain paragraph-to-paragraph gap. */
  .jpm-body-copy__divider {
    display: flex;
    justify-content: center;
    padding: 12px 0;
  }

  .jpm-body-copy__divider img {
    display: block;
    width: 32px;
    height: 32px;
    max-width: none;
  }

  /* ── Collage Footer ── Figma node 55:32 ("CollageFooter"), currently
     empty in Figma — see the HTML comment above this element for why
     no content is invented here. Pure closing space, on top of Essay
     Body's own 48px bottom padding, so the page ends with a deliberate
     rest rather than stopping right on the last paragraph. */
  .jpm-collage-footer {
    height: 40px;
  }

  /* Phones get the copyright line inside the paper column (.jpm-page)
     instead of on the page color below it. */
  .page-journal-post > .site-footer {
    display: none;
  }
}
