The preview card was there all along and invisible. It was positioned inside the paragraph it belonged to, and a flashcard is a small box with its overflow hidden — so the card was drawn and clipped, and the link read as doing nothing. I had "fixed" that by turning previews off on cards, which was the wrong end of the problem: the preview is what the link is for. It is drawn into the body now, placed from the link's own rectangle, so nothing between the two can clip it. That is a fix everywhere, not only on cards. Two things behind it: - **Clicking a link flipped the card back**, because the whole card is a flip target and the click bubbled — so the preview opened and the thing it was anchored to vanished in the same gesture. Only the empty parts of a card flip it now. - **There was nowhere for "Split view" to go** from a card. The deck now has a pane of its own: the article opens beside the card, the deck keeps its place, and following a reference out of the article replaces the pane rather than losing you. **The deck is boxed like the session player.** Header at the top, verdict at the foot, and only the card scrolls between them. A card with a picture on it is taller than the window, and the two buttons the whole exercise turns on were below the fold: you scrolled down to read the answer and back up to say whether you knew it. Unflipped, the foot offers Show answer rather than two buttons about a card you have not seen. And the four grey pills down the side of every row in Browse are one strip. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
81 lines
2.8 KiB
CSS
81 lines
2.8 KiB
CSS
/* Cross-reference links and their hover cards. */
|
|
|
|
.al-wrap { position: relative; display: inline; }
|
|
.al-link {
|
|
color: var(--primary);
|
|
text-decoration: none;
|
|
border-bottom: 1px solid color-mix(in srgb, var(--primary) 35%, transparent);
|
|
}
|
|
.al-link:hover { border-bottom-color: var(--primary); }
|
|
|
|
.al-card {
|
|
position: absolute;
|
|
z-index: 40;
|
|
left: 0;
|
|
top: calc(100% + 8px);
|
|
/* `is-floating` is the card drawn into the body: fixed to the window and
|
|
placed from the link's rectangle, so nothing between the two can clip it.
|
|
Above everything, because it is summoned deliberately and briefly. */
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
width: min(340px, 78vw);
|
|
padding: 12px 14px;
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 10px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.16);
|
|
font-size: 0.84rem;
|
|
line-height: 1.5;
|
|
text-align: left;
|
|
/* The card must hold the pointer. It used to be transparent to it, on the
|
|
idea that a hint should never sit between the reader and the link — but
|
|
the card is offset below the link and never covered it, while the pointer
|
|
travelling down to Split view crossed a body it could not enter, so no
|
|
mouseenter fired and the hide timer closed the card on the way. */
|
|
pointer-events: auto;
|
|
}
|
|
|
|
/* Bridges the 8px gap between the link and the card, so crossing it never
|
|
leaves the wrapper at all and the grace period is never needed. */
|
|
.al-card::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
top: -9px;
|
|
height: 9px;
|
|
}
|
|
.al-card.is-above::before { top: auto; bottom: -9px; }
|
|
.al-card.is-above { top: auto; bottom: calc(100% + 8px); }
|
|
.al-card.is-floating { position: fixed; z-index: 1290; width: min(340px, calc(100vw - 16px)); }
|
|
.al-card.is-floating.is-above { top: auto; }
|
|
.al-card-title { font-weight: 700; font-size: 0.92rem; color: var(--text); }
|
|
.al-card-excerpt { color: var(--text-muted); }
|
|
.al-card-meta { font-size: 0.75rem; color: var(--text-subtle); }
|
|
|
|
.al-card-actions { display: flex; gap: 6px; margin-top: 2px; }
|
|
.al-card-action {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 4px 9px;
|
|
background: none;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
font: inherit;
|
|
font-size: 0.72rem;
|
|
line-height: 1.4;
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
white-space: nowrap;
|
|
cursor: pointer;
|
|
}
|
|
.al-card-action:hover { border-color: var(--primary); color: var(--primary); }
|
|
.al-card-action:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
|
|
|
|
/* Touch has no hover, so the card arrives on the tap that would have followed
|
|
the link. It is the only route to the article there, so it must be shown. */
|
|
@media (hover: none) {
|
|
.al-card { width: min(340px, calc(100vw - 32px)); }
|
|
}
|