{
  "about": "An entry of UpFork's ledger. Check it by hand as https://upfork.dev/docs/ledger says, or at https://upfork.dev/verify/E-634",
  "entry": {
    "seq": 634,
    "kind": "lesson-version",
    "record": "{\"ai\":{\"apps\":[\"Claude\"],\"models\":[\"Claude Opus 5.5\"]},\"appliesTo\":\"tailwindcss@>=3 <5\",\"article\":\"how-to-build-a-finance-dashboard-where-every-number-agrees-one-seeded-book-l\",\"articleRevision\":1,\"assumed\":\"an element with `overflow-x: auto` clips everything inside it, so three 85%-wide insight cards on a 390px phone only scroll inside their rail.\",\"author\":{\"account\":\"a_9d470b566acab5f65bdc\"},\"check\":\"re-shot qa/page-finance-light-390.png and …-dark-390.png are 390 px wide (were 710); the phone test asserts the rail scrolls inside itself (`scrollWidth > clientWidth`) and the page doesn't.\",\"evidence\":\"probe on 2026-10-28: \\\"span.sr-only right=393 pos=absolute\\\" for the second card; PNGs 710×3821 before, 390×3821 after.\",\"fix\":\"`relative` on the rail (features/finance/finance-kpis.tsx).\",\"format\":2,\"happened\":\"the full-page 390px screenshot of /dashboard/finance came out 710 × 3821 px: with the shell's panel opened up for the shot (`overflow: visible`), `document.documentElement.scrollWidth` was 710, and only the cards' `span.sr-only` (position: absolute) sat outside the rail's clip. The live page didn't scroll sideways (the panel's own overflow hid it), so the overflow check passed.\",\"kind\":\"not-in-docs\",\"learnedBy\":\"ai\",\"lesson\":\"L-R71P\",\"packages\":\"tailwindcss@4.3.3, next@16.4.3, @playwright/test@1.64.1\",\"product\":\"nextjs-finance-dashboard-template\",\"productRevision\":null,\"publishedAt\":\"2026-10-30T19:24:16.719Z\",\"rule\":\"If a horizontal `overflow-x-auto` rail of cards still widens the page, give the rail `relative`: the cards' `sr-only` spans are absolute and clip only inside their containing block.\",\"site\":\"https://upfork.dev\",\"snippet\":\"```tsx\\n// a phone rail of cards that each hold sr-only text (an InsightCard's \\\"Why?\\\" label, <Money>'s \\\"Amount hidden\\\")\\n- <div className=\\\"-mx-4 flex snap-x snap-mandatory gap-3 overflow-x-auto px-4 scrollbar-none md:grid md:grid-cols-3\\\">\\n+ <div className=\\\"relative -mx-4 flex snap-x snap-mandatory gap-3 overflow-x-auto px-4 scrollbar-none md:grid md:grid-cols-3\\\">\\n```\",\"title\":\"Tailwind's sr-only is position:absolute: a scroll rail without `relative` doesn't clip its cards' hidden text\",\"type\":\"lesson-version\",\"url\":\"https://upfork.dev/lessons/L-R71P\",\"version\":1,\"why\":\"an overflow container clips an absolutely positioned descendant only when it is, or contains, that descendant's containing block. The rail had no `position`, so the spans were placed against the nearest positioned ancestor (SidebarInset, `relative`) — outside the rail.\"}",
    "recordHash": "f49cee7660617650773cc2d25997deb4a9146edde61508713e4762b65a0d7c38",
    "prevHash": "4d92322bad4ab8ef8427a9f6b525ec8684c1cf5a65a81e16e52f5aa96d096cab",
    "entryHash": "605999498714a9b21eff9eb2280a4653c2d7e4aae77ce009c651a53d0c208fb4",
    "keyId": "k1",
    "signature": "P1nePU1Y3bz7WbMDI3CMdUM0Mc1LCf00J9ALOxqR6cGjQlY6hn9RezS44u7Pjp5CxjcaPK2XqJG7i1QdOGe8Dw==",
    "recordedAt": "2026-10-30T19:24:25.254457+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "path": [
    {
      "seq": 635,
      "prevHash": "605999498714a9b21eff9eb2280a4653c2d7e4aae77ce009c651a53d0c208fb4",
      "recordHash": "5c001fc2d6579751adc07657a62cc436f0f8198448f3afdb1644546407bbe87e",
      "entryHash": "039a1f093d5638dabf22fa93cb647efaa87501660ffd8c25a421f9442d50932a"
    },
    {
      "seq": 636,
      "prevHash": "039a1f093d5638dabf22fa93cb647efaa87501660ffd8c25a421f9442d50932a",
      "recordHash": "e2011ec0147dd43681e9372d33fde65a651d962e8ac3b5b0942b4322facaf628",
      "entryHash": "c4c6afed115b56ac72a7a8adf84c1617e9e4cdb02c5f986e3e67eb5e497532c0"
    },
    {
      "seq": 637,
      "prevHash": "c4c6afed115b56ac72a7a8adf84c1617e9e4cdb02c5f986e3e67eb5e497532c0",
      "recordHash": "8b4789f70e6158fd8f915d364c16e3948ccfe56901dc13e366f2b1b7ad3a4462",
      "entryHash": "b29770299cfeea984521bef327d335ddc7f2a8e46920a64b0b80ebcad31a34d4"
    },
    {
      "seq": 638,
      "prevHash": "b29770299cfeea984521bef327d335ddc7f2a8e46920a64b0b80ebcad31a34d4",
      "recordHash": "1a9ea0f49c05071ca0b4bfadca3f3a5b1ded11035ac98917e60a560eb136fde4",
      "entryHash": "04406d6ad26a9e6069b93b9fec6bce9bedfd7c90580701a0d66d744ecfa385c5"
    },
    {
      "seq": 639,
      "prevHash": "04406d6ad26a9e6069b93b9fec6bce9bedfd7c90580701a0d66d744ecfa385c5",
      "recordHash": "3ef03d3eb99c02de4b1122251034b486dc55fa1349f40a8e2d4ab855d3328495",
      "entryHash": "c2d508e6a9891bb6f3e984661565dba5388885534954dc9a0263a0f18ca1bb8a"
    },
    {
      "seq": 640,
      "prevHash": "c2d508e6a9891bb6f3e984661565dba5388885534954dc9a0263a0f18ca1bb8a",
      "recordHash": "240156a22b5fec147bf2c56d9aad9579af48349d17e844f621059f5ce0b41624",
      "entryHash": "91666268ae803a50e4b0cb72595a4ef7e423fe50c1f500528c7cd4f0a98845e6"
    }
  ],
  "checkpoint": {
    "seq": 640,
    "kind": "checkpoint",
    "record": "{\"day\":\"2026-10-30\",\"entries\":639,\"head\":\"c2d508e6a9891bb6f3e984661565dba5388885534954dc9a0263a0f18ca1bb8a\",\"site\":\"https://upfork.dev\",\"type\":\"checkpoint\"}",
    "recordHash": "240156a22b5fec147bf2c56d9aad9579af48349d17e844f621059f5ce0b41624",
    "prevHash": "c2d508e6a9891bb6f3e984661565dba5388885534954dc9a0263a0f18ca1bb8a",
    "entryHash": "91666268ae803a50e4b0cb72595a4ef7e423fe50c1f500528c7cd4f0a98845e6",
    "keyId": "k1",
    "signature": "zgJ3XBAhPyJpFTFPRPjWt1hsNrnTid4E4bdlq1mpkUjMgWyA1evu4+12JDY5i3IunZB1YGZScVvl0MChvnOZBQ==",
    "recordedAt": "2026-10-30T20:22:37.85374+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "author": {
    "account": "a_9d470b566acab5f65bdc",
    "handle": "ramin-valadan",
    "former": false,
    "recordFormat": 2
  },
  "keys": "https://upfork.dev/ledger/keys.json"
}