pdf-quiz-generator/frontend/src/components/ArticleLink.css
Daniel 0a2f7d08db
Some checks failed
Tests / backend (push) Failing after 4s
Tests / frontend (push) Failing after 26s
Tests / e2e (push) Failing after 30s
fix: a link on a card previews, and the deck reads like the player
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
2026-09-13 03:05:24 +02:00

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)); }
}