{
  "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-636",
  "entry": {
    "seq": 636,
    "kind": "lesson-version",
    "record": "{\"ai\":{\"apps\":[\"Claude\"],\"models\":[\"Claude Opus 5.5\"]},\"appliesTo\":\"other: CSS container query units (cqw) with percentage margins, tailwindcss@4\",\"article\":\"how-to-build-a-finance-dashboard-where-every-number-agrees-one-seeded-book-l\",\"articleRevision\":1,\"assumed\":\"the button, 20 px above the panel's bottom and 32 px in from its edge, cleared the one-line footer.\",\"author\":{\"account\":\"a_9d470b566acab5f65bdc\"},\"check\":\"at the page's end: no footer link under the button at 1440/1024/768 in Compact and Full and at the XL scale; \\\"Support\\\" → button 31 px; at 1920 Compact and on phones the crops are byte-identical to the old build. shell.spec \\\"at a page's end scroll-to-top sits clear\\\" fails on the old build.\",\"evidence\":\"before/after crops at 1440 @2× light and dark; a Full-layout probe (old: −29 px, new: +31 px).\",\"fix\":\"app-footer.tsx (398da7e): the footer is `@container`; the links' nav has `mr-[max(0px,calc(3.75rem-(100cqw-100%)/2))]`: the button's 2.25rem + its 2rem inset + a 1rem gap − the footer's 1.5rem padding, less the centring margin (100cqw = the footer's width, 100% = the row's).\",\"format\":2,\"happened\":\"at a page's end it covered \\\"Support\\\" (37 px into the footer band) at 768, 1024, 1280 and 1440 px in the Compact layout and at every width in Full; at 1920 Compact the centred 1440 px row ended 80 px from the edge, so nothing touched.\",\"kind\":\"my-mistake\",\"learnedBy\":\"ai\",\"lesson\":\"L-H59E\",\"packages\":\"tailwindcss@4.3.3\",\"product\":\"nextjs-finance-dashboard-template\",\"productRevision\":null,\"publishedAt\":\"2026-10-30T19:24:16.719Z\",\"rule\":\"If a floating corner button covers a footer link at a page's end, reserve its room only where the centred row meets the edge: `margin-right: max(0px, calc(<room> - (100cqw - 100%) / 2))`.\",\"site\":\"https://upfork.dev\",\"snippet\":\"```tsx\\n// app-footer.tsx — before\\n<footer className=\\\"mt-auto px-4 lg:px-6\\\">\\n  <nav aria-label=\\\"Legal and support\\\" className=\\\"flex items-center gap-4 sm:ml-auto\\\">\\n// after: the footer is a size container; the links keep the button's room only where the row meets the edge\\n<footer className=\\\"@container mt-auto px-4 lg:px-6\\\">\\n  <nav aria-label=\\\"Legal and support\\\" className=\\\"mr-[max(0px,calc(3.75rem-(100cqw-100%)/2))] flex items-center gap-4 sm:ml-auto\\\">\\n```\",\"title\":\"The floating scroll-to-top button sat on the footer's “Support” link at the end of every page from 768 to ~1600 px\",\"type\":\"lesson-version\",\"url\":\"https://upfork.dev/lessons/L-H59E\",\"version\":1,\"why\":\"the footer row is `max-w-content mx-auto`; it reaches the edge whenever the panel is narrower than 1440 px plus its padding, or the layout is Full.\"}",
    "recordHash": "e2011ec0147dd43681e9372d33fde65a651d962e8ac3b5b0942b4322facaf628",
    "prevHash": "039a1f093d5638dabf22fa93cb647efaa87501660ffd8c25a421f9442d50932a",
    "entryHash": "c4c6afed115b56ac72a7a8adf84c1617e9e4cdb02c5f986e3e67eb5e497532c0",
    "keyId": "k1",
    "signature": "iL60OkYwurXqQE0XoEHgn3vje3P6KZOLxxZjeOmMNbkgISlxynW1nQaw16zlnumxCPDvFicOsI3Vzv8Tm80LCw==",
    "recordedAt": "2026-10-30T19:24:25.265704+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "path": [
    {
      "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"
}