Server-rendered cards inside a client carousel that scrolls rather than paginates, so all six links stay in the initial HTML and the row still works with JavaScript off. Three client islands, split by what each needs: a school, the whole selection, a DOM ref. The lede claims a similar intake only when no card came from tier 3, chips list what a school actually shares, a missing figure reads "Not published", and the neighbour's number carries no valence colour — green and terracotta mean "against England" everywhere else, and colouring it here would read as ranking the neighbours. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
66 lines
5.3 KiB
CSS
66 lines
5.3 KiB
CSS
.heading { font-family: var(--font-display); font-size: 1.4rem; letter-spacing: -0.4px; margin: 0; }
|
|
.lede { margin: 0.5rem 0 1.25rem; color: var(--text-secondary); max-width: 64ch; }
|
|
.caption { margin: 1rem 0 0; font-size: 0.72rem; color: var(--text-muted); }
|
|
|
|
.top { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
|
|
.arrows { display: flex; gap: 0.5rem; flex: none; }
|
|
.arrow { width: 44px; height: 44px; display: grid; place-items: center; cursor: pointer; border: 1px solid var(--border-strong); border-radius: 999px; background: var(--bg-card); color: var(--brand); }
|
|
.arrow:hover:not(:disabled) { border-color: var(--brand); background: var(--brand-bg); }
|
|
.arrow:disabled { opacity: 0.35; cursor: default; }
|
|
.arrow svg { width: 17px; height: 17px; }
|
|
|
|
/* A scroller, not a paginated view: every card is in the DOM and the arrows
|
|
only move the viewport across them. The 2px padding keeps focus rings from
|
|
being clipped — and is why the arrows' edge test needs a tolerance. */
|
|
.scroller { display: grid; grid-auto-flow: column; grid-auto-columns: calc((100% - 1.8rem) / 3); gap: 0.9rem; overflow-x: auto; scroll-snap-type: x mandatory; padding: 2px; margin: -2px; list-style: none; scrollbar-width: none; -ms-overflow-style: none; }
|
|
.scroller::-webkit-scrollbar { display: none; }
|
|
@media (max-width: 820px) { .scroller { grid-auto-columns: calc((100% - 0.9rem) / 2); } }
|
|
/* Touch widths (MOBILE.md): the arrows would take 96px from a 328px card and
|
|
crush the lede into four lines, for a control swiping already provides. They
|
|
go, and the documented right-edge fade carries the affordance — lifting at
|
|
the end of the travel, where there is nothing more to hint at. */
|
|
@media (max-width: 640px) {
|
|
.top { display: block; }
|
|
.arrows { display: none; }
|
|
.scroller { grid-auto-columns: 86%; mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
|
|
.scroller[data-at-end="true"] { mask-image: none; }
|
|
}
|
|
|
|
.school { position: relative; display: flex; flex-direction: column; scroll-snap-align: start; border: 1px solid var(--border); border-radius: 8px; padding: 1rem; background: var(--bg-card); }
|
|
.school:hover { border-color: var(--border-strong); }
|
|
|
|
.distance { margin: 0 0 0.6rem; font-size: 0.75rem; color: var(--text-muted); }
|
|
.name { font-family: var(--font-display); font-size: 1rem; line-height: 1.35; margin: 0 0 0.35rem; }
|
|
.name a { color: var(--text-primary); text-decoration: none; }
|
|
/* The whole card is the link target; the button sits above it on z-index. */
|
|
.name a::after { content: ""; position: absolute; inset: 0; border-radius: 8px; }
|
|
.name a:hover { color: var(--brand); text-decoration: underline; }
|
|
.meta { margin: 0 0 0.75rem; font-size: 0.78rem; color: var(--text-muted); }
|
|
|
|
.shared { display: flex; flex-wrap: wrap; gap: 0.35rem; list-style: none; margin: 0 0 0.85rem; padding: 0; }
|
|
.chip { font-size: 0.72rem; line-height: 1.4; padding: 0.25rem 0.5rem; border-radius: 999px; background: var(--brand-bg); color: var(--brand); border: 1px solid transparent; }
|
|
.chipLoose { font-size: 0.72rem; line-height: 1.4; padding: 0.25rem 0.5rem; border-radius: 999px; background: transparent; color: var(--text-muted); border: 1px solid var(--border); }
|
|
|
|
.metric { margin-top: auto; padding-top: 0.8rem; border-top: 1px solid var(--border); }
|
|
/* No valence colour here, deliberately: green and terracotta mean "against the
|
|
England average" everywhere else on the site, and colouring a neighbour
|
|
against this school would read as ranking the neighbours. */
|
|
.value { font-family: var(--font-display); font-size: 1.6rem; font-weight: 700; letter-spacing: -0.6px; margin: 0; color: var(--text-primary); }
|
|
.valueAbsent { font-size: 0.95rem; font-weight: 600; margin: 0; color: var(--text-muted); }
|
|
.metricLabel { margin: 0.25rem 0 0; font-size: 0.75rem; color: var(--text-secondary); }
|
|
.metricRef { margin: 0.1rem 0 0; font-size: 0.75rem; color: var(--text-muted); }
|
|
|
|
.add { position: relative; z-index: 1; margin-top: 0.85rem; width: 100%; min-height: 44px; font: inherit; font-size: 0.82rem; font-weight: 500; cursor: pointer; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--bg-card); color: var(--brand); }
|
|
.add:hover { border-color: var(--brand); background: var(--brand-bg); }
|
|
.add[aria-pressed="true"] { border-color: var(--brand); background: var(--brand-bg); font-weight: 600; }
|
|
|
|
.footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.85rem; margin-top: 1.25rem; padding-top: 1.1rem; border-top: 1px solid var(--border); }
|
|
.footer p { margin: 0; font-size: 0.78rem; color: var(--text-muted); }
|
|
.footer strong { display: block; font-size: 0.88rem; font-weight: 600; color: var(--text-primary); }
|
|
/* Coral is the one decisive action per screen, and in this section this is it. */
|
|
.compare { min-height: 44px; padding: 0 1.25rem; border-radius: 8px; font-size: 0.88rem; font-weight: 600; background: var(--action); color: var(--action-on); border: 1px solid var(--action); text-decoration: none; display: inline-flex; align-items: center; }
|
|
.compare:hover { background: var(--action-strong); border-color: var(--action-strong); }
|
|
.compare[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
|
|
|
|
.srOnly { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|