| 1 | /* ------------------------------------------------------------------ */ |
| 2 | /* Utilities — focus, selection, links, sheet motion */ |
| 3 | /* ------------------------------------------------------------------ */ |
| 4 | |
| 5 | /* ---------- focus + selection ---------- */ |
| 6 | /* The one focus treatment on the site: a 2px ring at a 3px offset in the |
| 7 | accent of whatever depth the control sits in (the stage re-declares |
| 8 | --ring). Components may add the bioluminescent halo (--glow-focus) as a |
| 9 | box-shadow; none restyles or removes the ring. */ |
| 10 | ::selection { background: var(--selection); } |
| 11 | :focus-visible { outline: var(--gpui-focus-width) solid var(--ring); outline-offset: var(--gpui-focus-offset); } |
| 12 | |
| 13 | /* ---------- links ---------- */ |
| 14 | a { color: inherit; text-decoration: none; } |
| 15 | |
| 16 | /* A link in running text: accent ink, a quiet underline that firms on |
| 17 | hover. `.body-link` is the legacy name for the same recipe. */ |
| 18 | .link, |
| 19 | a.body-link, |
| 20 | .prose a { |
| 21 | color: var(--accent); |
| 22 | text-decoration: underline; |
| 23 | text-decoration-thickness: 1px; |
| 24 | text-underline-offset: 0.2em; |
| 25 | text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); |
| 26 | transition: text-decoration-color var(--dur-state) var(--ease-out); |
| 27 | } |
| 28 | .link:hover, |
| 29 | a.body-link:hover, |
| 30 | .prose a:hover { text-decoration-color: var(--accent); } |
| 31 | .link .icon { margin-inline-start: 0.25em; } |
| 32 | |
| 33 | /* ---------- the mobile sheet ---------- */ |
| 34 | /* The sheet arrives (opacity plus a 4px rise) and leaves faster than it |
| 35 | came. No per-item stagger. Reduced motion mounts and unmounts at once. */ |
| 36 | @media (prefers-reduced-motion: no-preference) { |
| 37 | .mm-panel { |
| 38 | animation: mm-in var(--dur-arrive) var(--ease-out) both; |
| 39 | } |
| 40 | |
| 41 | .mm-panel.mm-closing { |
| 42 | animation: mm-out var(--dur-exit) var(--ease-in) both; |
| 43 | pointer-events: none; |
| 44 | } |
| 45 | |
| 46 | /* Content that arrives after an action (a retried feed, a result set). */ |
| 47 | .arrive { |
| 48 | animation: mm-in var(--dur-arrive) var(--ease-out) both; |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | @keyframes mm-in { |
| 53 | from { opacity: 0; transform: translateY(-0.25rem); } |
| 54 | to { opacity: 1; transform: translateY(0); } |
| 55 | } |
| 56 | |
| 57 | @keyframes mm-out { |
| 58 | from { opacity: 1; transform: translateY(0); } |
| 59 | to { opacity: 0; transform: translateY(-0.25rem); } |
| 60 | } |
| 61 | |
| 62 | /* ---------- responsive chrome ---------- */ |
| 63 | @media (max-width: 900px) { |
| 64 | .site-nav-inner { gap: 1rem; } |
| 65 | .site-github-link { display: none; } |
| 66 | } |
| 67 | |
| 68 | /* Anchor fallback; page-level scroll-mt utilities can override it. */ |
| 69 | :where([id]) { scroll-margin-top: 5rem; } |
| 70 | |
| 71 | [dir="rtl"] .icon-flip { transform: scaleX(-1); } |
| 72 |