78 lines (70 loc) · 6.43 KB
 1@use "../theme" as *;
 2@use "../vars" as v;
 3
 4// === No-JS fallback: the original inline collapsible box ===
 5// The floating circle / sheet / sidebar below are progressive enhancements
 6// gated behind `.js` (set in head.html before paint), so without JavaScript
 7// the table of contents stays a plain, working <details> box.
 8.post-toc, .post-toc * { box-sizing: border-box; }
 9.post-toc { margin-bottom: 2rem; padding: 1rem 1.25rem; border: 1px solid theme(border); border-radius: 0.5rem; background: theme(card); }
10.post-toc__summary { display: inline-flex; align-items: center; justify-content: flex-start; gap: 0.4rem; font-size: 0.75rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.08em; color: theme(muted); cursor: pointer; list-style: none; user-select: none; }
11.post-toc__summary::-webkit-details-marker { display: none; }
12.post-toc__burger, .post-toc__header { display: none; } // JS-mode chrome
13// Pixel caret: five 2px "pixels" drawn with box-shadow, flipped down while closed.
14.post-toc__chevron { order: -1; margin-right: 0.2rem; position: relative; width: 10px; height: 6px; transform: scaleY(-1); }
15.post-toc__chevron::before { content: ""; position: absolute; top: 0; left: 4px; width: 2px; height: 2px; background: currentColor; box-shadow: -2px 2px currentColor, 2px 2px currentColor, -4px 4px currentColor, 4px 4px currentColor; }
16.post-toc[open] .post-toc__chevron { transform: none; }
17.post-toc__body { margin-top: 1rem; }
18.post-toc__body ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.5rem; }
19.post-toc__body li { line-height: 1.4; }
20.post-toc__body a { font-size: 0.9rem; color: theme(subtle); transition: color 0.15s ease; }
21.post-toc__body a:hover { color: theme(heading); }
22.post-toc__body ul ul { padding-left: 1rem; margin-top: 0.5rem; }
23
24// === JS enhancement ===
25.js {
26  // Single source of truth for the active item (scroll-spy only runs with JS).
27  .post-toc__body a.is-active { color: theme(accent); }
28
29  // --- Small screens: a static bottom-right circle + overlay sheet ---
30  @media (max-width: 1399.98px) {
31    // The circle never changes shape/position; the sheet covers it when open.
32    .post-toc { position: fixed; right: 1.25rem; bottom: 1.25rem; left: auto; z-index: 50; margin: 0; padding: 0; border: none; background: transparent; --toc-anim: 0.2s; }
33    .post-toc__label, .post-toc__chevron { display: none; }
34    // Round, toned down toward the page background so it sits quietly
35    // in the corner; hover still lights it up with the accent.
36    .post-toc__summary { display: flex; align-items: center; justify-content: center; width: 3rem; height: 3rem; border-radius: 50%; background: color-mix(in srgb, theme(card) 60%, theme(bg)); color: color-mix(in srgb, theme(muted) 70%, theme(bg)); border: 1px solid color-mix(in srgb, theme(border) 55%, theme(bg)); transition: color 0.15s ease, border-color 0.15s ease; }
37    @media (hover: hover) { // avoid sticky :hover on touch
38      .post-toc__summary:hover { color: theme(accent); border-color: theme(accent); }
39    }
40    .post-toc__burger { display: block; }
41
42    // Overlay: instant backdrop (covers the sticky header too, so it dims
43    // along with the rest of the page instead of staying lit above it), then
44    // the sheet slides in over the circle.
45    .post-toc[open]::before { content: ""; position: fixed; inset: 0; z-index: 101; background: rgba(0, 0, 0, 0.5); }
46    .post-toc__sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 102; display: none; flex-direction: column; max-height: 65vh; background: theme(bg); border-top: 1px solid theme(border); border-radius: 0.75rem 0.75rem 0 0; box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.2); opacity: 0; transform: translateY(0.75rem); transition: opacity var(--toc-anim) ease, transform var(--toc-anim) ease, display var(--toc-anim) allow-discrete; }
47    .post-toc[open] .post-toc__sheet { display: flex; opacity: 1; transform: translateY(0); @starting-style { opacity: 0; transform: translateY(0.75rem); } }
48
49    .post-toc__header { display: flex; align-items: center; justify-content: space-between; padding: 0.6rem 1rem; border-bottom: 1px solid theme(border); }
50    .post-toc__title { font-size: 0.85rem; font-weight: 700; color: theme(heading); }
51    .post-toc__close { display: flex; align-items: center; padding: 0.2rem; margin: -0.2rem; background: none; border: none; font-family: "Silkscreen", monospace; font-size: 0.7rem; letter-spacing: 0.05em; color: theme(muted); cursor: pointer; transition: color 0.15s ease; }
52    @media (hover: hover) { .post-toc__close:hover { color: theme(text); } }
53
54    .post-toc__body { margin: 0; overflow-y: auto; padding: 0.6rem 1rem calc(0.85rem + env(safe-area-inset-bottom, 0px)); -webkit-overflow-scrolling: touch; }
55    .post-toc__body ul { gap: 0.35rem; }
56    .post-toc__body ul ul { padding-left: 0.85rem; margin-top: 0.35rem; }
57    .post-toc__body a { font-size: 0.78rem; color: theme(muted); transition: color 0.15s ease; }
58    @media (hover: hover) { .post-toc__body a:hover { color: theme(heading); } }
59  }
60
61  // --- Wide screens: sticky sidebar ---
62  @media (min-width: 1400px) {
63    .post-toc { position: fixed; top: var(--toc-top, var(--toc-top-min, calc(v.$header-height + 2rem))); left: max(1rem, calc((100vw - v.content-width()) / 2 - 220px)); width: 200px; margin-bottom: 0; padding: 0; border: none; border-radius: 0; background: transparent; --toc-top-min: calc(v.$header-height + 2rem); z-index: 2; visibility: hidden; }
64    .post-toc__summary { display: inline-flex; align-items: center; justify-content: flex-start; font-size: 0.7rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.7; margin-bottom: 0.75rem; gap: 0.4rem; color: theme(muted); }
65    .post-toc__label { display: inline; }
66    .post-toc__chevron { display: block; margin-left: 0; }
67    .post-toc__body { max-height: calc(100dvh - v.$header-height - 6rem); overflow-y: auto; margin-top: 0; }
68    .post-toc__body::-webkit-scrollbar { width: 3px; }
69    .post-toc__body::-webkit-scrollbar-track { background: transparent; }
70    .post-toc__body::-webkit-scrollbar-thumb { background: theme(border); border-radius: 2px; }
71    .post-toc__body::-webkit-scrollbar-thumb:hover { background: theme(muted); }
72    .post-toc__body ul { gap: 0.35rem; }
73    .post-toc__body a { font-size: 0.8rem; line-height: 1.5; display: block; word-wrap: break-word; overflow-wrap: break-word; color: theme(muted); }
74    .post-toc__body a:hover { color: theme(text); }
75    .post-toc__body ul ul { padding-left: 0.75rem; }
76  }
77}
78