A small framework built on two ideas: ld-* classes for structure, data-ld-* attributes for state and variants. No dependencies — link the prebuilt files in dist/ and go. (The build step is only for editing the framework itself.)
<button class="ld-btn" data-ld-variant="primary" data-ld-size="lg"> Run </button>
data-ld-variant: primary · outline · ghost · danger | data-ld-size: sm · md · lg
data-ld-shadow: sm · md · lg · hard | data-ld-interactive lifts the card on hover
data-ld-error flips a field into its error state
Dropdown, tabs, and modal — powered by ldcss.js, wired entirely through data-ld-* attributes
ldcss pairs structural classes with state-carrying attributes, so a component's markup reads like a small config file.
Include ldcss.css and ldcss.js. Everything else is attributes on plain HTML — no build step.
v3.3.0 — Media: ld-img, ld-media (fixed-shape wrappers, data-ld-ratio), ld-video, ld-figure, captions and overlays, ld-masonry (CSS columns, real masonry where the browser has it) and ld-gallery. Layout primitives: ld-cluster, ld-sidebar-layout, ld-switcher, ld-cover. Component
lifecycle: ldcss.init / destroy / reinit on one component or a whole
subtree, ldcss.component(name), ld:{component}:init / :destroy events, listeners that go away with their
element, automatic clean-up of removed markup. Tokens: --ld-border-radius-sm/-lg, --ld-transition-fast/-slow, --ld-content-width, --ld-line-height-*,
--ld-opacity-*.
v3.2.0 — Accessibility and bug-fix release. Form field edges use a
new --ld-border-control token (3:1 or better in both themes; they were
1.2:1) and the focused border is --ld-focus-border. .ld-input, .ld-textarea, .ld-select, the tag input, the command palette, the context menu and the
range slider all keep a focus indicator in Windows High Contrast (transparent outline instead of none; the range thumb gets a real ring). The light danger colour is darker
so white text on it passes (5.1:1). Toasts stay 5 s or more (longer for longer text), pause while the tab is
hidden, and data-ld-toast-default-duration sets your own default. Dark
mode follows the OS with no JavaScript and no flash (prefers-color-scheme, plus dist/ldcss-theme.js for a saved choice), and ldcss.theme.get() / set() is new. Nested themes no longer cancel data-ld-shadow or data-ld-unstyled set
higher up. Dialogs: stacked modals each give focus back to what opened them, Escape closes one layer at a
time, and the focus trap skips hidden elements. Fixed a crash on key-less keydown events (browser autofill).
v3.1.1 — Search bar: the input is now styled (ld-input is added for you) and the magnifier is a real button next to it, so
clicking it searches just like pressing Enter. New ld:search:submit
event; in a <form> the button submits the form. data-ld-search-button="false" keeps the compact icon-inside style. Fixed:
Escape closed the search dropdown and the browser's own "clear search" immediately reopened it.
v3.1.0 — New: context menu (data-ld-context-menu), toast queue and notification centre (ldcss.toast, ldcss.notify), resizable
panels (data-ld-resizable), general-purpose disclosure (data-ld-disclosure), search bar with fuzzy matching (data-ld-search, ldcss.fuzzy), easy
tables (data-ld-table), sizing / flex / grid / transition / transform
utilities, and a unified event API (ldcss.on, ldcss.once, ldcss.off, ldcss.emit, wildcard "*"). The combobox
gained remote sources with debounce, loading / empty / error states, request cancellation, result templates
and renderers. ldcss now watches the page and initialises markup added later (data-ld-observe="false" opts out). Accessibility: aria-current, dropdown menu keys, inert
behind dialogs, tooltip names, 24px hit areas, forced-colors support, ldcss.a11y.audit(). The cheat sheet was rewritten with pages, a sidebar and
search.
v3.0.2 — The nav brand links to the landing page (index.html) on every page. Relative, so it also works when you open the
files straight from disk or host them in a sub-folder.
v3.0.1 — Minor bugfixes to pages and carousel. The carousel arrows
no longer jump when pressed: they were centred with a transform that the
button's press nudge replaced. They are now centred with insets, so they stay centred at any carousel
height; the press nudge uses translate and so adds to any transform
instead of replacing it. New: index.html landing page.
v3.0.0 — breaking: ldcss.css is now built from
src/ (npm run build → dist/) and sits in cascade layers (ld.tokens → ld.base → ld.components → ld.utilities → ld.escape → ld.variants):
utilities now beat components regardless of selector specificity, and anything you write outside a layer
beats all of ldcss. .ld-nav-brand no longer shows a $ by default — opt in with data-ld-mark="$" (any text works). New: ld-shell/ld-sidebar (see
demo-sidebar.html), ld-hero, ld-section, ld-row, ld-hover:*/ld-focus:*/ld-focus-visible:* variants, ld-underline/ld-no-underline/ld-ring. Fixed: data-ld-notheme is no
longer a hand-copied duplicate of the light tokens (it had drifted: wrong code color and success color);
JetBrains Mono is self-hosted instead of loaded from Google Fonts.
v2.4.0 — a small, backward-compatible batch: ld-footer is the bottom counterpart to ld-nav that ldcss was missing — same padding and surface, just border-top instead of border-bottom
since it anchors the end of the page rather than the start. New ld-shadow-up/-sm/-lg utility trio mirrors the existing ld-shadow-soft-sm/-soft/-soft-lg scale (same opacities, same dark-theme handling) but casts the
shadow upward — built to pair with ld-footer, or any other element
pinned to the bottom of the viewport. And ld-bg-* gains five semantic
values — accent/danger/success/warning/info — joining surface/raised/transparent, reading the same
tokens ld-text-danger and the badge/alert variants already use.
v2.3.0 — new command palette action: data-ld-command-action="goto:target". If target starts with # it's treated as an
in-page anchor — smooth-scrolls to it (instantly under prefers-reduced-motion), updates the URL via history.pushState so the hash is shareable/back-button-able, and moves focus
onto the target (adding tabindex="-1" first if it isn't already
focusable) so keyboard and screen-reader users land in the right place, same as a normal anchor-link click.
Anything else — goto:/pricing, a full URL — just navigates there. Before
this, jumping to a page or section from the command palette meant wrapping the item in a real <a href> (still supported, and still the right call for a plain link
with no scroll/focus choreography needed) — goto is for when you want an
action-triggered jump instead, e.g. a "Go to pricing" result that isn't literally a link in the surrounding
markup.
v2.2.0 — three consistency fixes, all backward-compatible (no markup
changes required). Chips: [data-ld-chip][data-ld-active="true"] now shows a checkmark on its own via a
:has()-guarded ::before, so a bare
<button data-ld-chip>Label</button> looks right without also
hand-adding a .ld-chip-check span; pages that already include the span
are unaffected — :has() detects it and steps aside rather than doubling
the mark. Tags: data-ld-tag/data-ld-tag-remove are now first-class equivalents of .ld-tag/.ld-tag-remove in both the CSS
and the click/backspace-to-remove handlers, so tag markup can follow the same
attribute-for-interactive-state convention as chips/segments instead of being the one place that only had
classes; JS-generated tags (typed into data-ld-tags-input) now carry
both the class and the attribute. Responsive utilities: order joins the per-breakpoint set — ld-sm:order-*/ld-md:order-*/ld-lg:order-*/ld-xl:order-* (1–5, first, last), for the common case of
reordering a two-column hero's text/art on mobile without a non-responsive ld-order-* affecting every breakpoint at once.
v2.1.0 — new components: native ld-select gets a real arrow (light/dark aware; [multiple] is left bare); ld-dot
notification badge for avatars/icons (data-ld-count, data-ld-variant); data-ld-input-clear
and data-ld-password-toggle, both slotting into the existing ld-input-group affix pattern; ld-btn-group (+ data-ld-split for a
split button); ld-skip-link; and two table additions — data-ld-sticky-head (pins the header row inside a scrolling ancestor) and
click-to-sort headers via th[data-ld-sort] (data-ld-sort-key, per-cell data-ld-sort-value for sorting formatted text by a hidden number/date, fires
ld:table:sort). New utilities: ld-aspect-*/ld-object-*, ld-opacity-*, ld-leading-*, generic
motion (ld-animate-spin/-pulse/-bounce, separate from the one-off keyframes already built into
toast/skeleton/spinner), a small ld-dark:*/ld-light:* variant set for one-off property flips (retheme with tokens
instead for anything bigger), ld-scrollbar-thin, and ld-safe-{top,bottom,left,right} for notched-device insets. Accessibility:
ld-sr-only-focusable (the reveal-on-focus half of ld-sr-only, also what ld-skip-link is
built on); a forced-colors: active pass that drops shadows and lets
Windows High Contrast Mode's own palette carry buttons/cards/inputs; and a prefers-reduced-transparency fallback that swaps ld-glass's blur for a solid surface. Theming: new semantic status tokens
--ld-success/--ld-warning/--ld-info (+ -text pairs, themed for
light/dark/notheme) replace what used to be one hardcoded hex value inline in the alert and terminal-window
rules; new --ld-weight-* and --ld-leading-* scales; and the --ld-z-*
stacking values (already exposed as ld-z-* utility classes) are now also
real custom properties that every overlay component reads, instead of each hardcoding its own layer number.
Minor non-breaking visual change: the alert info
variant's rail/title color moved off --ld-text onto the new --ld-info blue, to match every other semantic variant being a real color
rather than "just text-colored." JS: dropdown/popover now return focus to their trigger when closed with
Escape while you were navigating inside them (modal/offcanvas/command already did this); window.ldcss.destroy() disconnects entrance-animation observers before you
remove a chunk of DOM; window.ldcss.debounce() is exposed for wiring an
async/remote combobox source (the built-in local-list filter doesn't need it).
v2.0.0 — Bootstrap-parity batch (breaking visual change: container).
.ld-container now steps its max-width at each breakpoint (100% fluid
below 640px, then 600/900/1100/1320px) instead of a single fixed 1100px cap — pages relying on the old
fluid-up-to-1100px behavior at in-between viewport widths (roughly 640–1099px) will render narrower than
before at those sizes; ld-container-sm/ld-container-wide are unaffected. New: a real 12-column grid (ld-grid-row/ld-col-*/ld-offset-*, responsive at every breakpoint, distinct from the even-split
ld-grid) for asymmetric layouts; a carousel (data-ld-carousel, with autoplay, dots, and prev/next); navbar collapse
(data-ld-navbar-collapse, the inline "hamburger below a breakpoint,
always-visible above it" pattern, distinct from the slide-in ld-offcanvas); floating labels (ld-form-floating); opt-in native validation styling (.ld-validate, using :user-invalid/:user-valid so it only reacts after interaction, not on an empty required
field's first paint); richer skeleton placeholders (button/avatar shapes, a width scale, a paragraph pattern
with uneven line lengths); and scrollspy (data-ld-scrollspy on a
container of anchor links — this page's own nav uses it now, watch the underline move as you scroll).
Responsive utilities gained padding/margin (all-sides, sizes 0/2/3/4/6/8), text-size, and width axes at
every breakpoint. Tabs and the segmented control now use roving tabindex — Tab jumps straight to content,
arrow keys move between options within the group. Every overlay component (modal, offcanvas, dropdown,
popover, accordion, tabs, command palette, carousel) now dispatches bubbling ld:{component}:show/hide CustomEvents,
so one listener higher up the DOM can react to any instance instead of patching click handlers. RTL pass:
offcanvas, tooltip left/right placement, pull-quote, terminal title, avatar-group overlap, input affix,
timeline, dropdown menu, and popover all switched from physical left/right to logical properties (inset-inline-*, margin-inline-*, border-inline-*) — they now mirror correctly under dir="rtl"; toast position was deliberately left physical, since a
"top-right" notification shouldn't relocate based on text direction. Known gap: overlay slide/enter
animations (offcanvas transform, in particular) are still physical, not direction-aware — positioning is
correct under RTL, the transition direction itself isn't yet.
v1.1.0 — new components: data-ld-segmented/data-ld-segment
(segmented control, for a value rather than a view — contrast with tabs), data-ld-chip/data-ld-chips="single"
(interactive filter chips, distinct from the display-only ld-tag), ld-input-group/ld-input-affix (icon or
unit alongside an input), data-ld-combobox (filtered, keyboard-navigable
search-inline — distinct from the command palette, which is search-in-a-modal), ld-empty (the "no results" pattern), ld-timeline (a vertical, open-ended activity feed — contrast with the
fixed-stage stepper), and ld-icon (a sizing convention for inline SVGs,
not an icon set). Stepper is now interactive: add a bare data-ld-stepper attribute alongside the existing ld-stepper class to opt in — data-ld-clickable="true" lets people jump to any step, data-ld-toggle="step-next"/"step-prev"
wires up buttons, and data-ld-step-panels="#selector" pairs it with
show/hide panels the way tabs pair with tab panels; old static ld-stepper markup with no data-ld-stepper attribute is untouched. Toast container now reads data-ld-toast-position on <body>
(top/bottom × left/center/right; top-right stays the default) at the moment it's first created. Theme now
falls back to prefers-color-scheme: dark on a first visit with no saved
choice — an explicit toggle always wins after that. Responsive utilities gained lg (1200px) and xl (1440px) breakpoints,
and every breakpoint (sm/md/lg/xl) now also covers flex-row/flex-col, text-left/center/right, and gap-0/2/4/6, not just display and grid-cols. Documented (no code change): a one-off custom brand color beyond
the seven ld-accent-* presets is just --ld-accent/--ld-accent-text set inline
on any element, the same mechanism the presets use.
v1.0.0 — modern default (breaking visual change). ldcss no longer
defaults to ldcss's original sharp/mono/hard-shadow look. Out of the box it's now: rounded corners (--ld-radius 0px → 10px), a soft layered shadow instead of a hard offset
(--ld-shadow/new --ld-shadow-lg), a
thinner neutral-gray border (--ld-border-width 2px → 1px, border color
no longer near-black), and a system sans-serif font (--ld-font-family
now defaults to new token --ld-font-sans; use ld-font-mono to opt back in — code/pre/kbd/terminal are unaffected, they
read --ld-font-mono directly and stay mono). Every bordered/shadowed
component was touched: buttons, badges, cards, inputs, dropdowns, modals, alerts, toasts, popovers,
tooltips, the command palette, and more all pick up the new radius/shadow tokens; progress bars, switches,
tags, and the range thumb are now pill/circle-shaped; button press and card hover use a normal soft lift
instead of the old shadow-cancel trick; input focus is a soft ring (color-mix()) instead of a hard-offset box. Two new escape hatches for
getting the old (or a fully custom) look back: data-ld-shadow="hard"
restores the original offset shadow anywhere you set it — on <html> for the whole page or on one element — the same mechanism the
old data-ld-shadow="soft" used, just inverted now that soft is the
default; data-ld-unstyled resets radius/shadow/border-weight/accent-fill
to neutral on a container so a stylesheet loaded after ldcss.css can restyle it cleanly without fighting
specificity. The old hard-offset sm/md/lg shadow-depth tiers on data-ld-shadow are now soft blur tiers to match. Migration:
if you were relying on the old look, add data-ld-shadow="hard" to <html> and ld-font-mono to your
body/container for the closest match — corners and border color aren't independently revertible via
attribute yet, override --ld-radius/--ld-border directly if you need them back too.
v0.12.0 — token-driven shadows and fills. New --ld-shadow token (composed from the existing offset/color tokens) that
ld-btn and ld-card now read for
their resting shadow, plus data-ld-shadow="soft" to re-skin it to a
blurred look wherever it's set — on <html> for the whole page, or
on a single button/card — the same way data-ld-theme="dark" works for
color. New --ld-accent-fill token (defaults to --ld-accent) now backs primary button and badge fills, so a brand can drop
in a gradient in one place without touching component rules. Consistency fix: ld-badge, the outer border of ld-alert,
and ld-accordion-item now read --ld-border-width instead of a hard-coded 1px, matching every other structurally-bordered component — hairline
dividers (table rows, card footers, list separators) are unchanged on purpose. New utility: ld-font-mono, completing the ld-font-sans/ld-font-serif trio for
opting a subtree back into monospace.
v0.11.0 — new components: ld-blockquote/ld-pull-quote, ld-divider/ld-divider-v, ld-stat, ld-avatar-group. New utilities:
ld-text-3xl/4xl (display type scale
— previously capped at 2xl), ld-container-sm/wide (built as compound selectors so they can't be defeated by source order
the way §3b–3i/old §29 were), ld-print-hidden/ld-print-only. Forms: data-ld-success="true" alongside the existing error state. New JS: data-ld-animate="fade-up|fade-down|fade-left|fade-right|fade-in" entrance
animations via IntersectionObserver, fully skipped (elements shown immediately) under prefers-reduced-motion.
v0.10.0 — structural fix: moved the utility-class system (previously
§3b–3i) and Escape Hatches (previously §29) to the true end of the stylesheet (§38–§39). Both were plain
single-class selectors sitting before most components, so any later component rule with the same
specificity silently won ties and defeated them — e.g. ld-pad-a-8 on a
.ld-card did nothing, because .ld-card's own padding rule came later in the file. No class names changed,
only file position — but if you'd copied any component's CSS out of context, re-copy it, since
order-dependent behavior like this doesn't survive being lifted out of the full file.
v0.9.0 — fixes from a real-world readiness test (built a full page
with zero custom CSS). --ld-font-family is now a real inheritable token:
ld-font-sans/ld-font-serif cascade
to every descendant (buttons, inputs, tabs, headings, etc.) instead of needing to be repeated per element —
code/pre/ld-kbd stay mono on purpose. .ld-nav-brand can drop its $ mark with
data-ld-mark="none". New utilities: ld-italic, ld-aspect-{square,video,4-3,3-2}, ld-mx-auto/ld-my-auto, ld-link-reset. ld-shadow-none/soft-sm/soft/soft-lg now also win on :active/:disabled/:hover/:focus, so a softened button/card/input no longer snaps back to the hard
offset shadow mid-interaction.
v0.8.0 — added typography (ld-text-{xs..2xl}, ld-font-*, ld-truncate, ld-line-clamp-*), color
(ld-text-danger, ld-bg-*),
position/z-index (ld-relative/absolute/fixed/sticky, ld-inset-0, ld-z-* incl. named aliases matching this file's own dropdown/modal/toast
stacking), flex extras + generic grid (ld-self-*, ld-order-*, ld-grid-cols-*),
visibility/interaction (ld-sr-only, ld-cursor-*, ld-select-none, ld-overflow-*), and the first responsive variants (ld-sm:d-*, ld-md:d-*, ld-sm:grid-cols-*, ld-md:grid-cols-*).
Lives in ldcss.css §3d–3i.
v0.7.0 — added generated spacing/layout utility classes: ld-pad-{side}-{size} and ld-mar-{side}-{size} (side: a/t/r/b/l/v/h, size: 0–8 mapped to --ld-space-*), plus negative margins (ld-mar-t-n3), ld-gap-*, and display/flex
helpers (ld-d-*, ld-flex-*, ld-items-*, ld-justify-*, ld-text-{left,center,right}, ld-w-*,
ld-max-w-*). These are real classes in ldcss.css §3b–3c, not a naming convention to remember.
v0.6.0 — pagination is now data-driven: data-ld-paginate="#target" + data-ld-page-size="3" on a .ld-pagination element auto-generates the right number of page buttons from
the target's row/item count, and clicking a page actually shows/hides that slice of rows. Manual
(hand-written) pagination markup still works as before.
v0.5.2 — bugfix: three components had markup but no wiring. Command
palette items now do nothing by default unless given data-ld-command-action — added real actions to the demo. List group items
are now clickable and select themselves (data-ld-active) among siblings.
Pagination buttons now actually update the active page and disable prev/next at the ends (mark them with
data-ld-page="prev"/"next").
v0.5.1 — bugfix: [data-ld-dropzone] defaulted to inline layout when used on a <label>, so its border only wrapped the first line and the filename
text spilled outside the box. Now explicitly display: flex.
v0.5.0 — added offcanvas, stepper, command palette (⌘K), range
slider, dropzone, rating, tag input. Added ld-scale-* density presets,
ld-accent-* per-element color swap, ld-glass/ld-flat surfaces. ARIA wiring
(aria-expanded/aria-hidden/aria-selected, dialog roles, focus trap + focus return, live-region toasts) and a
prefers-contrast: more pass.
v0.4.0 — added escape-hatch utilities: ld-round*, ld-border-{width}px-{style},
ld-shadow-soft*, ld-font-sans /
ld-font-serif — for opting out of the sharp/hard-shadow/monospace
defaults per element.
v0.3.0 — added kbd, copy-to-clipboard, terminal window, spinner, toast, table, pagination, list group, switch, avatar, popover, skeleton loader.
v0.2.0 — added alerts, accordion, breadcrumbs, tooltip, progress
bar. Added data-ld-notheme to freeze a subtree's theme. Fixed
low-contrast code blocks on light theme (new --ld-code-text token).
v0.1.0 — buttons, cards, nav, forms, dropdown, tabs, modal, theming.
data-ld-variant: info · success · warning · danger | data-ld-dismiss="alert" removes it
data-ld-accordion="single" makes items mutually exclusive; omit it and they open independently
data-ld-notheme to any
element and its subtree stays in its light appearance regardless of the page theme.This card ignores the page theme toggle — try it
Press ⌘ + K to open the command menu.
| Name | Role | Status |
|---|---|---|
| Lena Dijksma | Maintainer | active |
| Sam Okafor | Contributor | idle |
| Priya Rao | Contributor | active |
| Tomás Ferreira | Contributor | idle |
| Naomi Achterberg | Reviewer | active |
| Kwame Boateng | Contributor | idle |
| Elin Karlsson | Maintainer | active |
| Marcus Bui | Contributor | idle |
| Ana Ionescu | Reviewer | active |
9 rows, 3 per page → data-ld-page-size="3" on the pagination element builds 3 page buttons
automatically.
Classes for structure, data-ld-* attributes for state. MIT licensed.
Opt individual elements out of (or back into) the rounded/soft-shadow/sans-serif defaults
ld-border-1px-dotted · ld-border-2px-dashed · ld-border-3px-solid · ld-border-2px-double
ld-{pad|mar}-{a·t·r·b·l·v·h}-{0..8}, plus
gap/display/flex helpers
Full pattern reference and negative-margin syntax are in the README and cheat sheet.
ld-text-xl ld-font-bold ld-uppercase
ld-text-sm ld-text-muted — smaller, muted body copy
ld-truncate: this sentence is much too long to fit and gets cut off with an ellipsis
ld-line-clamp-2: this paragraph is long enough to wrap across several lines, but gets clipped after exactly two of them with a clean overflow cut, regardless of how much more text follows.
Resize the window past 640px/960px to see ld-sm:d-* / ld-md:d-* in the cheat sheet
reference — they're documented there rather than demoed live here since this page doesn't have a resizable
frame.
Six months in, the numbers finally caught up with the intuition. Priya Rao, Head of Growth
Also new: ld-container-sm/ld-container-wide (max-width variants, safe against source order — see §37e),
data-ld-animate entrance animations (paired with ldcss.js, respects reduced-motion), ld-print-hidden/ld-print-only, and data-ld-success="true" on inputs alongside the existing error state.
Offcanvas slides in from either edge; stepper tracks progress through a flow
Press ⌘/Ctrl + K anywhere on this page, or use the button in the nav
"design" uses the original .ld-tag/.ld-tag-remove classes; "css" uses the newer data-ld-tag/data-ld-tag-remove
attributes (v2.2.0) — both remove the same way, including tags you type into the input.
New in v1.1.0 — all attribute-driven, no bespoke classes to memorize beyond the ones shown here
"Senior" has no .ld-chip-check span in its markup
— the checkmark is generated automatically (v2.2.0) so it still matches the other two.
Also new: the .ld-stepper below is now interactive (data-ld-stepper + data-ld-clickable="true")
— click a step, or use the buttons.
New in v2.0.0 — plus this whole page's nav is now a live scrollspy demo (data-ld-scrollspy), and every overlay component below fires ld:*:show/hide events you can listen for
New in v2.1.0 — plus generic motion/scrollbar/opacity/aspect-ratio utilities and a forced-colors pass (not pictured, see cheat sheet)
New in v2.4.0
This page's own footer (scroll down) uses ld-footer — same padding/surface as ld-nav, flipped to border-top, paired
with ld-shadow-up.
New in v3.0.0 — the sidebar has its own page: demo-sidebar.html
New in v3.1.0 — the full reference is in the new cheat sheet
Animated, and out of the tab order while closed.
| Name | Role | Age |
|---|---|---|
| Zoë Martin | Designer | 31 |
| Alan Turner | Engineer | 9 |
| Bea Okafor | Manager | 100 |
| Dana Lee | Support | 45 |
| Eli Park | Designer | 27 |
| Fay Chen | Engineer | 52 |
New in v3.3.0 — the full reference is in the cheat sheet
| Name | Score |
|---|---|
| Ada | 91 |
| Grace | 88 |
| Linus | 72 |
| Margaret | 95 |
This is a modal opened with data-ld-toggle="modal". It closes on Escape,
backdrop click, or the × button.