Component classes
Class names moss emits on auto-generated components. Target them directly in .moss/theme/style.css.
| Class | Kind | Description |
|---|---|---|
.moss-cards | container | A listing of child pages — auto-generated from a folder's children, or hand-picked by a :::grid {.summary} fence, which emits this same container so both read through one card renderer. The single canonical container; layout density on data-layout (grid for cover-led tiles, list for cover+excerpt rows, minimal for text-only year-grouped indexes). Wrapped in .moss-cards-container to scope CSS container queries. |
.moss-cards-container | container | Outer wrapper around .moss-cards that carries container-type: inline-size so the grid can use @container queries instead of viewport @media queries. Layout-agnostic — wraps any data-layout variant. A body embed also reads the same placement vocabulary every other embed kind does: data-width, a moss-align-left / moss-align-right float class, and a content-relative size as inline style="width:NN%", which replaces the data-width token when both are written — the frontmatter-synthesized listing never carries any of the three. |
.moss-cards-minimal-year-group | container | Year-grouped section in minimal card layout (e.g. blog index). Modifier --summary collapses past years. |
.minimal | instance | Bare co-class on a minimal year group, alongside the prefixed name. Retained because themes in the wild key on it. |
.moss-cards-minimal-year-group--summary | container | BEM modifier on .moss-cards-minimal-year-group. Applied to year groups that should render in collapsed summary form (e.g. past years on a blog index). |
.moss-card | instance | v1 collapsed shape — single canonical instance class inside .moss-cards. Layout-specific styling targets .moss-cards[data-layout=X] .moss-card. Tag is <a> for ordinary cards and <div> for linkblog cards ([data-linkblog]). |
.moss-card-cover | instance | Cover media slot inside .moss-card. Gets .moss-card-no-cover modifier when no image is present, or data-cover="quote" when a sibling card in the same listing has a cover and this one doesn't. |
.moss-card-no-cover | instance | Modifier applied to .moss-card-cover when no cover media is available. |
.moss-card-content | instance | Text content slot inside a grid-layout .moss-card (kicker + title + meta). |
.moss-card-row | instance | Row wrapper inside a list-layout .moss-card holding body + cover side-by-side. |
.moss-card-body | instance | Text body slot of a list-layout .moss-card. |
.moss-card-title | instance | Title inside .moss-card. |
.moss-card-meta | instance | Type-aware metadata slot (date for articles, count for folders, domain for links), with the page's resolved place appended after its date when location: names one — a bare folder's count never gets a place of its own, but a folder with its own date: (on its home page) shows that date and place first, then its article count after them. Renders ABOVE the title in horizontal mode — filling the kicker position when the explicit kicker slot is unset. To the right of the title in vertical CJK mode (the horizontal kicker position transposed). Meta IS the visual kicker, with the same uppercase overline treatment. |
.moss-card-kicker | instance | Eyebrow / overline above the title inside .moss-card. |
.moss-card-kicker-favicon | instance | Favicon inline before the domain, on a [data-external] card's kicker — emitted only when one is cached for the link. Same ImageContext::Favicon synthesis the retired .link-preview-favicon used (bare <img>, no manifest, no <picture>, no LQIP). |
.moss-card-permalink | instance | Author's-archive link mark (★, U+2605) emitted INSIDE .moss-card-kicker for linkblog cards (those whose child page has external_url:). The card title links to the external canonical (publisher); the ★ links to the local archival copy at the page's slug. Reads as part of the kicker line — "Publisher · Year ★". Semantically distinct from Daring-Fireball's linkblog ★ (which marks discussion permalink alongside commentary) — here the local copy is the same content preserved for resilience and stable bylines, not added commentary. Putting <a>★</a> inside the kicker is valid because linkblog cards emit <div class="moss-card" data-linkblog> (not <a>) as the outer element — see the data-linkblog attribute described on .moss-card. |
.moss-card-title-link | instance | Anchor wrapping the .moss-card-title <h3> on linkblog cards. Ordinary cards have the whole-card <a class="moss-card"> as the link target — but linkblog cards switch the outer to <div> so the kicker can host a nested ★ anchor, which means the title needs its own anchor to stay clickable. Same canonical-URL target as the other inner anchors (moss-card-cover-link, moss-card-description-link). |
.moss-card-cover-link | instance | Anchor wrapping the .moss-card-cover on linkblog cards — same role as .moss-card-title-link but for the cover image / media. Targets the canonical (external) URL. |
.moss-card-description-link | instance | Anchor wrapping the .moss-card-description on linkblog cards — same role as .moss-card-title-link but for the description excerpt. Targets the canonical (external) URL. |
.moss-card-description | instance | Excerpt / description paragraph inside a .moss-card — below the title in both grid- and list-layout cards. |
.moss-embed-more | instance | Trailing "More →" link on a truncated children listing (emitted when children_limit caps the embed); links to the folder's full index. Rendered as a sibling immediately after .moss-cards-container, so it sits outside the listing's flex gap and binds to the list via its own margin-top. |
.moss-folder-item | instance | Modifier on .moss-card-minimal for folder-type entries in minimal listings. |
.moss-folder-title | instance | Title text of a folder entry in minimal listings. |
.moss-folder-description | instance | Description paragraph of a folder entry in minimal listings. |
.moss-folder-link | instance | Modifier on .moss-prefix-link for folder-type links in minimal listings. |
.moss-prefix-link | instance | Link with a prefix span (date or icon) and a title span. Used inside minimal cards. |
.moss-prefix-link-prefix | instance | Prefix slot of a prefix-link (typically a date). |
.moss-prefix-link-title | instance | Title slot of a prefix-link. |
.title | instance | Bare co-class beside moss-prefix-link-title, the counterpart of date on the prefix span. Both predate the prefixed names and are still emitted for themes that key on them. |
.moss-prefix-link-suffix | instance | Optional trailing slot of a prefix-link. |
.moss-callout | standalone | Obsidian-style callout. The Obsidian-compat .callout class is co-emitted; type lives on data-type (v1). |
.callout | standalone | Obsidian-compat class co-emitted on every callout for theme parity. Type lives on data-type (v1). |
.callout-title | instance | Title row of a callout. |
.callout-content | instance | Body container of a callout. |
.moss-embed | standalone | Base class on every typed embed. Kind on data-type (v1), including audio and video. Ambient video: add data-loop via ![[clip.mp4|loop]]. .moss-embed-audio and .moss-embed-video still ride alongside as co-classes on the element (see their own entries) — .moss-embed-pdf / -notebook / -table / -iframe / -3d are the ones retired in Phase 1c, collapsed into data-type. |
.moss-embed-figure | standalone | Wraps a captioned non-image embed (video, audio, pdf, iframe, 3D model, folder listing), the way .moss-image wraps a captioned image. Carries the caption's <figcaption> and, because it is the outermost element, the embed's data-width, float class AND any content-relative size (inline style="width:NN%") — the embed element inside keeps .moss-embed and its data-type, and fills the figure at width:100% rather than carrying any placement of its own. |
.moss-embed-pending | instance | Co-class on .moss-embed while the embedded file is still coming down from iCloud Drive. moss neither waits for the download nor bakes in an error box: it asks for the file, says plainly that it is still arriving, and lets the watcher rebuild the page when it lands. The default CSS does not style this — it is a hook for themes that want to mark the placeholder as provisional. |
.moss-embed-audio | instance | Co-class alongside .moss-embed on every audio element — not collapsed away by Phase 1c the way the other kind co-classes were. The default CSS keys off [data-type=audio] rather than this class, so it is a hook for themes, not a style dependency. |
.moss-embed-video | instance | Co-class alongside .moss-embed on every video element — not collapsed away by Phase 1c the way the other kind co-classes were. The default CSS keys off [data-type=video] rather than this class, so it is a hook for themes, not a style dependency. |
.moss-embed-ipynb | instance | Alias of .moss-embed-notebook; consolidation pending. |
.moss-embed-error | instance | Error state for embeds whose target cannot be resolved. |
.moss-embed-missing | instance | Fallback rendered when a folder-list embed (![[journal/]]) targets a folder that does not exist or cannot be resolved. Distinct from .moss-embed-error (file/wikilink resolution failure) — this one is specifically the folder-listing path. |
.moss-hero | standalone | Hero banner section at the top of a page (cover image + title). v1 adds data-width for author-controlled sizing. |
.moss-hero-content | instance | Text content slot inside .moss-hero — text laid ON the image. For text ABOUT the image, see .moss-hero-caption. |
.moss-hero-caption | standalone | Caption or credit for a hero image, from :::hero {caption="…"}. A SIBLING of .moss-hero, immediately after it — not a child: the section is a fixed-height cropping frame, and a photographer's credit has to survive as text below the picture rather than be printed across it. Rendered as inline markdown, so a credit can be a link, exactly like a byline: / colophon: row. |
.moss-hero-slides | instance | Wrapper holding the .moss-hero-slide images of a multi-image hero; the CSS ambient crossfade cycles one slide visible at a time. |
.moss-hero-slide | instance | One background slide of a multi-image hero. Emitted only when the hero has 2+ images; slides crossfade ambiently via site.css keyed on the section's data-slides. First slide is the reduced-motion static fallback. |
.moss-image | standalone | Wrapper around an inline <img> for sizing and figure semantics. data-width carries a named width token (body|wide|page|screen); a content-relative width is instead emitted as inline style="width:NN%" (set by the editor drag-resize), which also forces the inner image to fill that percent box. Images narrower than the content column center horizontally. |
.moss-align-left | standalone | Floats an embed element to the left of body text (editorial runaround) — an image, a captioned figure (.moss-image, .moss-embed-figure), a bare .moss-embed, or a .moss-cards-container listing. Defaults max-width to 50% on desktop unless the element carries its own data-width or content-relative size, and collapses to a full-width, unfloated block below 48rem regardless. CSS :has() escalates an image's float to its wrapping <figure class="moss-image"> when present; every other kind carries the class on its own outermost element already. Mirrors WordPress's alignleft convention. |
.moss-align-right | standalone | Floats an embed element to the right of body text (editorial runaround) — an image, a captioned figure (.moss-image, .moss-embed-figure), a bare .moss-embed, or a .moss-cards-container listing. Symmetric counterpart to .moss-align-left. Mirrors WordPress's alignright convention. |
.moss-article-title | instance | Article-page H1 title emitted from frontmatter. |
.moss-heading-anchor | instance | Clickable permalink appended inside an author-written body heading that carries a slug id; links to the heading's #-fragment. The element is EMPTY — the # a reader sees is drawn by site.css as ::after content, so selecting a heading never copies it. Never emitted for a level-1 heading (a page's own title, not a section of it — the id is still there, so an existing #title link still resolves) or for any heading on the home page (levels 2-6 included: a reader lands there by visiting the site, not by a deep link into one of its sections). Also never emitted for a display title: the auto-injected moss-article-title H1, a :::hero overlay heading, and a :::grid cell heading all get none. |
.moss-grid | container | Generic grid container (used by profiles, link previews, etc.). Modifier classes: profiles, featured, no-cards, summary. summary REPLACES this container rather than decorating it: the fence emits .moss-cards-container > .moss-cards[data-layout="list"] instead, so a .moss-grid never reaches the page and a column count is dropped — scroll is dropped the same way when both are written on one fence. v1 adds data-width (P9); a later release adds data-scroll. |
.moss-grid-card | instance | Card instance inside .moss-grid. Today emits sibling classes link-card / friend-card / no-cards; v1 collapses to data-kind. |
.moss-gallery | container | Image gallery container. v1 adds data-width (P9). |
.moss-gallery-item | instance | Single image entry inside .moss-gallery. |
.moss-buttons | container | Container for a row of .moss-btn buttons. v1: the inverted variant is on data-style="inverted". |
.moss-btn | standalone | Generic button primitive. Role on data-role (v1). |
.moss-btn__label | instance | Label span inside .moss-btn. |
.moss-btn__check | instance | Success checkmark slot inside .moss-btn. |
.moss-btn__spinner | instance | Loading spinner slot inside .moss-btn. |
.moss-subscribe | standalone | Newsletter subscribe block (auto-injected into footer when email channel configured). |
.moss-subscribe-script | instance | Marks the <script> moss injects into <head> when a page carries a subscribe form. It is a handle, not a styling hook — a theme or a test uses it to find (or suppress) moss's own subscribe behaviour without matching on script contents. |
.moss-subscribe-form | instance | Form element inside .moss-subscribe. |
.moss-btn-slot | instance | Fixed-width slot wrapping a form's submit button; used by both the subscribe and comment forms to prevent layout shift across idle/loading/success states. |
.moss-subscribe-status | instance | Status message shown after submit (success/error). |
.moss-subscribe-status__icon | instance | Icon slot inside .moss-subscribe-status. |
.moss-subscribe-landing | standalone | Standalone subscribe landing page surface (larger variant). |
.moss-series-nav | standalone | Series navigation bar (prev/next/collection) on series pages. |
.moss-series-nav-links | instance | Row holding prev/next links in series nav. |
.moss-series-nav-link | instance | Individual link inside series nav. Modifiers: moss-series-nav-prev, moss-series-nav-next, empty (placeholder). |
.empty | instance | Co-class on a series-nav link with nowhere to go — the previous link on the first entry, the next link on the last. The element is still emitted so the pair keeps its layout. |
.moss-series-nav-prev | instance | Previous-page modifier on a series nav link. |
.moss-series-nav-next | instance | Next-page modifier on a series nav link. |
.moss-series-nav-arrow | instance | Arrow glyph inside a series-nav link. |
.moss-series-nav-title | instance | Title text of the destination page in a series-nav link. |
.moss-series-nav-collection | instance | Collection-listing slot in series nav (sibling pages). |
.moss-series-nav-collection-row | instance | Row inside the collection listing of series nav. |
.moss-series-nav-position | instance | Where this page sits in its series — "2 of 3" / 「第 2 篇,共 3 篇」. Counts only the pages still in the reading order, so a page that stepped out with series: false is not in the total. Omitted when the folder holds a single page. |
.moss-collection-cover | standalone | Header surface on a collection landing page. |
.moss-collection-cover-row | instance | Row inside .moss-collection-cover. |
.moss-collection-cover-body | instance | Body content slot inside .moss-collection-cover. |
.moss-input | standalone | Generic form input primitive. |
.moss-field | container | Form field group (label + input). Modifier --inline for horizontal layout. |
.moss-label | instance | Label primitive for .moss-field. Modifier --small for compact form. |
.moss-link | standalone | Inline-link primitive (resets <button> chrome too). Use --subtle for muted variant. |
.moss-field--inline | instance | BEM modifier on .moss-field for horizontal label+input layout (used by settings UI primitives). |
.moss-label--small | instance | BEM modifier on .moss-label for compact form (used by services settings rows). |
.moss-info-grid | container | Two-column aligned label+value rows (CSS grid with display: contents children). Used by the deployment settings panel; ships in the default theme so authors can reuse the layout. |
.moss-row | container | Horizontal flex row of equal-flex .moss-field children. Form-row layout helper shipped in the default theme. |
.moss-input-feedback | instance | Auto-save status hint slot under .moss-field. Three state modifiers: --success, --error, --fade-out. |
.moss-input-feedback--success | instance | Success state modifier on .moss-input-feedback. |
.moss-input-feedback--error | instance | Error state modifier on .moss-input-feedback. |
.moss-input-feedback--fade-out | instance | Transient fade-out modifier on .moss-input-feedback (applied after a success message to dismiss it). |
.moss-comments | standalone | Comments surface (per-site SQLite backend or Artalk legacy). |
.comment-form-slot | instance | Placeholder the comment form is rendered into. Kept distinct from the form itself so a reply form can be moved between slots without re-rendering the form. |
.comment-form | instance | The comment submission form. data-state carries the submission lifecycle, so a theme can style submitting and error states without watching the network. |
.comment-form-meta | instance | Row holding the commenter identity fields (name, and email where configured), as distinct from the comment body textarea. |
.comment-form-status | instance | Live region announcing the result of a comment submission. an assertive live region is deliberate: the reader has just acted and is waiting on the answer. |
.comment-form-submit | instance | Co-class on the comment form's submit button, alongside moss-btn. aria-busy tracks the in-flight submission. |
.comment-field | instance | A text input inside the comment form. Applied to every field so a theme styles them once rather than per name. |
.moss-service-inactive | instance | Co-class applied to .moss-comments and .moss-subscribe-form when the backing service is not configured. Hidden by default in published sites and revealed inside the preview chrome so authors can see the inactive surface during editing. |
.moss-preview-popup | chrome | Floating link-preview popover injected at document.body level by the runtime preview.js. Fetches /_moss/previews.json and renders a hover card with title, description, and excerpt for internal links. |
.moss-preview-title | instance | Title slot inside .moss-preview-popup. |
.moss-preview-desc | instance | Description slot inside .moss-preview-popup (from frontmatter description). |
.moss-preview-text | instance | Excerpt slot inside .moss-preview-popup (auto-extracted from the linked article body). |
.moss-skip-link | chrome | First focusable element in <body>, before the nav island and header. Visually hidden until it receives keyboard focus, then jumps to <main id="main-content"> (WCAG 2.4.1). Themes may restyle it but should keep it off-screen at rest and visible on :focus. |
.moss-colophon | chrome | Footer colophon credit appended by moss. Shows the moss mark alone at rest, quiet in the same muted grey as the footer above it; on hover or keyboard focus the mark takes its ink and the name fades in beneath it, without moving the mark. |
.moss-colophon-icon | instance | Wraps the moss mark inside .moss-colophon — the mark is substituted whole, so the class and aria-hidden sit on a wrapper rather than on the <svg>. Owns the mark's size here (1.25rem) and its resting quiet — the mark inherits the link's muted colour until the credit is hovered or focused, when it takes the ink .moss-mark names for the ground. Decorative; the link's aria-label carries the accessible name. |
.moss-colophon-label | instance | Localized attribution wording inside .moss-colophon. Transparent at rest and faded in on hover/focus, positioned out of flow beneath the mark so the reveal shifts nothing — it stays in the DOM because it is the link's accessible name. Carries .moss-wordmark for the face. |
.moss-mark | chrome | The moss mark wherever moss draws it: black or near-white ink with the green drop lifted on a dark ground, never the muted colour of wording beside it. Its rules live in mark.css, which the app's launcher shares; the colophon's .moss-colophon-icon is the one instance in a built site. Size is the surface's to set, and so is any quieting — a surface may repaint the mark by setting --moss-mark-paint / --moss-mark-drop-paint, and time the change with --moss-mark-fade. |
.moss-wordmark | chrome | moss's name beside or beneath the mark. In Chinese it is set in Long Cang, the running hand that matches the mark's real ink, keyed on the element's inherited lang; the Latin moss stays in the body face. Size is the surface's to set — the colophon's label is one instance. |
.moss-shell-frame | chrome | App-shell frame surface (preview chrome). |
.moss-mobile-frame | chrome | Runtime marker the preview bridge adds to <html> when the shell is in mobile device-preview mode. The shell now owns chrome clearance by insetting the preview iframe, so no CSS keys off this class and it currently has no effect; it is retained as a revert path and may be removed. |
.main-nav | chrome | Top site navigation bar. Legacy non-moss- prefix kept for theme parity. |
.date-line | chrome | Byline row under an article title: the publication date on the left, the reading-size control on the right. Emitted only when the page has a date. |
.date | instance | The formatted publication date inside .date-line. Text is localized to the page's language. |
.moss-byline | container | Credit block under the page title, below .date-line when there is one. Emitted from the byline frontmatter field on every page kind — articles, folder indexes, the homepage and plain pages alike — one .moss-byline-row per authored line. On a page moss gives no title of its own (the homepage, a home: true folder page, a plain page) it sits under the author's own opening <h1>, or at the top of the page content when the body has none. Absent when the field is. |
.moss-byline-row | instance | One credit line. Its content is the author's text rendered as inline markdown, so a row may contain links or emphasis. moss does not know which part is a role and which is a name — style the whole row. |
.moss-article-colophon | container | Credit block at the FOOT of the page, emitted from the colophon frontmatter field — where the piece first ran, contributor biographies, production credits. Same rows as .moss-byline, different end of the page. Emitted on every page kind: inside <article> on an article page, and last in the page content everywhere else — after the children listing on a folder index or the homepage — where the enclosing element is not an <article> despite the class name. Unrelated to .review-colophon, which is the review feature's book card. |
.moss-article-colophon-row | instance | One foot-credit line, rendered as inline markdown exactly like .moss-byline-row. |
.site-name | instance | The site title link at the left of the nav bar. On a non-home page the same slot may instead carry .breadcrumb-segment. Absent on every page under [site] header = "nav", which drops the brand from the header in favor of a leading Home item in .nav-links. |
.breadcrumb-segment | instance | One ancestor link in the nav-left breadcrumb trail, used in place of .site-name once the page is below the site root. |
.nav-icons | chrome | Right-hand icon cluster in the nav bar (search, theme toggle, and similar). Stationary chrome, present whether or not the site has nav links. |
.nav-left | chrome | Left group of the nav bar. Holds either .site-name or the breadcrumb trail, never both — or, under [site] header = "nav", neither: the element itself is not emitted, and .nav-right takes the full row. |
.nav-right | chrome | Right group of the nav bar: the mobile menu button, the nav links, and the icon cluster, in that order. |
.nav-links | chrome | The nav link list. The link for the page currently being viewed additionally carries the bare class active — style .nav-links .active, not a moss- class. Under [site] header = "nav" the list always opens with an unstyled Home link ahead of the site's own nav items, carrying active and aria-current="page" together while on the home page. That mode drops the breadcrumb trail, so a nav item whose section contains the page being viewed — without being that exact page — carries active and aria-current="true" instead of "page", the one remaining cue for which section a deep page is under. |
.site-logo | instance | Optional logo image inside the site-name link. Decorative by construction (alt="" + aria-hidden), because the adjacent text already names the site. |
.breadcrumb-label | instance | The final, non-linked breadcrumb segment — the page you are on. .breadcrumb-segment is the linked form for ancestors. |
.breadcrumb-separator | instance | The / between breadcrumb segments. Restyle or hide this rather than trying to remove it from the markup. |
.mobile-menu-button | chrome | The hamburger. Emitted on every page and hidden by media query above the mobile breakpoint — it is not conditionally rendered, so a rule that shows it always will. |
.nav-search-btn | instance | Search button in the nav icon cluster. Its glyph is .search-icon. |
.search-icon | instance | The magnifier glyph. Sized in em and stroked with currentColor, so it follows the button's font-size and color rather than needing its own rule. |
.nav-theme-btn | instance | Light/dark toggle in the nav icon cluster. Its glyph is .theme-toggle-icon. |
.theme-toggle-icon | instance | The sun/moon glyph. One SVG whose clip path animates between states — restyle it, but do not expect two separate icons to swap. |
.nav-lang-toggle | chrome | The language switcher. Present only when the site has more than one edition among the three the switcher resolves (English, Simplified Chinese, Traditional Chinese) — a ja/ or fr/ tree publishes but adds no entry here. |
.nav-lang-current | instance | The edition being viewed, as inert text rather than a link — style the current-language affordance here. |
.nav-lang-link | instance | A link to another edition of the same page. Carries hreflang, so [hreflang="en"] is a stable hook for per-language styling. |
.moss-nav-island | chrome | Floating navigation island: a one-line bar, aligned to the text column, revealed on scroll-up once the masthead has left the screen. Opt-in — a site gets none until it sets [site].floating_nav = true (the Services-tab toggle writes that key). On a site that opted in, the markup is emitted on every page with a breadcrumb trail but only ever shows where the page has a contents table to offer: two or more section headings. --moss-nav-island-display: none forces it off from CSS, media query included. |
.moss-nav-island-bar | instance | The visible rounded bar. Its width follows --moss-nav-width/--moss-content-width, so it lines up with the article text rather than with the window. |
.moss-nav-island-trail | instance | The breadcrumb inside the island. Same segment classes as the masthead's, plus the current page as a final crumb. It never wraps: ancestors fold into .moss-nav-island-more until the row fits. |
.moss-nav-island-current | instance | The page you are on, as the trail's last crumb. The only crumb permitted to truncate — an ancestor either fits whole or folds away. |
.moss-nav-island-more | instance | Stands in for the ancestor levels the trail had to drop. Opens the levels menu on click; names them on hover via data-tooltip. Never opens on hover — a touch device has none, and that is the width where folding happens. |
.moss-nav-island-actions | instance | Button cluster at the island's end edge. Holds the sections button only — theme, language and search stay in the masthead. |
.moss-nav-island-sections | instance | Opens this page's section list. Always present in an emitted island, because an island only ever shows on a page with two or more sections — so the button always has something to open. |
.moss-nav-island-menu | instance | Popover opened by .moss-nav-island-more or .moss-nav-island-sections. Every row reserves a leading gutter for the current-row rule, so the labels line up in one column whether or not a row is marked. |
.moss-breadcrumb-more | instance | The masthead trail's counterpart to .moss-nav-island-more: stands in for the ancestor levels the trail folded, opens the levels menu on click, names them on hover via data-tooltip. Emitted (hidden) only when the trail has a middle to fold — three or more crumbs. |
.moss-breadcrumb-menu | instance | Popover listing the masthead trail's folded ancestor levels, opened by .moss-breadcrumb-more. A sibling of .nav-left (which clips its own overflow), positioned against .nav-content. Same shape as .moss-nav-island-menu. |
.moss-nav-island-progress | instance | Reading-progress track along the island's own bottom edge — not a separate bar across the window. Currently measures document scroll. |
.moss-nav-island-progress-fill | instance | The filled portion of the progress track. Its width is written inline by the site runtime; with JavaScript off it stays at 0 and the track reads as empty. |
.footer-default | chrome | The generated footer link row, emitted only when the site has no authored footer.md. Authoring a footer replaces it, so a rule targeting this stops applying the moment the site gains one. |
.footer-link | instance | One link in the generated footer row (RSS and similar). Off-site ones also carry data-external. |
.moss-child-section-divider | instance | Divider rule between auto-generated child sections. |
.moss-unknown-shortcode | standalone | Fallback wrapper emitted for any :::name fence whose name is not a registered shortcode. The body is still parsed as markdown and a build warning names the shortcode, so a misspelling degrades to a styled region rather than losing content. |
.moss-recent | container | Auto-generated list of recent posts. Sorted newest-first; date and description slots are filled per child. No default CSS in the bundled theme — theme authors style it freely. IMPORTANT: emitted by the EMAIL/newsletter path only. On a web page, :::recent renders its fallback body as ordinary markdown and emits no list, because the per-page processor has no access to the build's aggregate document slice; a :::recent block with an empty body therefore produces nothing at all on a web page. To list posts on a page today, rely on the automatic child listing a folder home emits (moss-cards), and give any :::recent block a fallback body. |
.moss-recent__date | instance | Per-entry date slot inside .moss-recent (BEM child). Format is YYYY-MM-DD, derived from frontmatter date. Empty string when the post lacks a parseable date. |
.moss-recent__desc | instance | Per-entry description slot inside .moss-recent (BEM child). Sourced from frontmatter description; empty when unset. |
.moss-ambient-video | standalone | JS-injected wrapper around a video[data-loop] element. Provides the positioning context for .moss-ambient-toggle and the [data-paused] state hook. Not emitted by the Rust synthesizer — ambient-video.ts creates it at init. |
.moss-ambient-toggle | instance | Chrome-free pause/play toggle button for ambient loop videos. Injected by ambient-video.ts. Keyboard-focusable; aria-label toggles between "Pause video" and "Play video". Visible on hover/focus of .moss-ambient-video and always visible when [data-paused]. Satisfies WCAG 2.2.2 Level A (Pause, Stop, Hide). |
.moss-math | standalone | A LaTeX equation. In P1 the element holds the author's own markdown source — `--- |
| title: Component classes | ||
| uid: 0da56c25 | ||
| weight: 42 | ||
| translationKey: docs-reference-components | ||
| description: The stable .moss-* class names emitted by moss's auto-generated components. Target these in .moss/theme/style.css. |
Class names moss emits on auto-generated components. Target them directly in .moss/theme/style.css.
/ $ delimiters included — HTML-escaped: an honest fallback that never shows a blank where an equation was written, and never deletes the delimiters of prose that merely looked like math. Requires [site].math (default on). |
| .moss-math-scroll | container | Horizontal-scroll container the build path wraps around typeset display math (svg.moss-math[data-moss-math="display"]). On a narrow viewport a wide equation scrolls inside this box at its natural size rather than shrinking to unreadability or pushing the page into horizontal overflow. Emitted only by P2's typeset path; the P1 <code> fallback is never wrapped. A display SVG left unwrapped still cannot overflow the page — it falls back to scaling down via max-width: 100%. |
| .moss-table-scroll | container | Horizontal-scroll wrapper the renderer emits around every Markdown table and every CSV/TSV embed (.moss-embed[data-type="table"]). Keeps the <table> semantically intact (unlike a display:block table, which breaks column layout and assistive-tech table semantics) while letting a wide table scroll inside its own box instead of pushing the page into horizontal overflow. tabindex="0" makes an overflowing table keyboard-scrollable. |
| .moss-scroll-dots | container | Position dots after a :::grid N {scroll} row, one per card. Added by the scroll-row runtime script, never by the build, so a page without scripts keeps the plain scrolling row. Cards in view carry .is-visible; the first of them is aria-current. Hidden when the row has nothing to scroll, and in print. |
| .moss-scroll-dots-viewport | container | Clipping wrapper directly inside .moss-scroll-dots, around .moss-scroll-dots-track. overflow: hidden crops the track to what's visible and touch-action: pan-y reserves the horizontal gesture for the pointer-driven scrub instead of ceding it to page panning. In dynamic mode (data-indicator="dynamic" on the ancestor, more than ten cards) it also fixes its inline-size to exactly seven dot-slots so a longer set of dots slides through a stable window; in the plain dots mode it sizes to its content and shows every dot. Added by the scroll-row runtime script, never by the build. |
| .moss-scroll-dots-track | container | Flex row of dot buttons inside .moss-scroll-dots-viewport. Slides via transform: translateX() driven by the --moss-scroll-dot-start custom property the script sets on navigation, over a 0.22s transition — suppressed while the reader is actively dragging (.moss-scroll-dots[data-scrubbing] on the ancestor, so the track tracks the pointer 1:1) or under prefers-reduced-motion: reduce. Added by the scroll-row runtime script, never by the build. |
| .moss-col-right | instance | Right-aligned table cell (<th>/<td>). Applied to a whole column when the author right-aligned it in GFM (\|--:\|) or when the column auto-detects as numeric, so figures register on their trailing digits. Pairs with the table's font-variant-numeric: tabular-nums. |
| .moss-col-center | instance | Center-aligned table cell (<th>/<td>). Applied to a whole column the author center-aligned in GFM (\|:-:\|). |
| .moss-search | chrome | Site-search overlay. Not emitted by the build — the client runtime (_moss/js/search.<hash>.js, shipped only when the build wrote a Pagefind index) constructs this subtree lazily on the first open, so a reader who never searches downloads no index and materializes no DOM. Opened by the nav's .nav-search-btn, by /, or by ⌘K/Ctrl+K. BEM children carry the interior: __backdrop (translucent page-coloured scrim, not an opaque modal takeover), __panel (top-anchored at 18vh, fixed 18px radius at any height), __field/__input, __progress (1px accent hairline, delayed 200ms so fast queries never flash it), __seam (hairline inset by the corner radius), __status (idle / no-matches line, sharing one vertical slot with the results so the panel never jumps), __results/__row/__link/__title/__excerpt. Selection is a 2px --moss-color-ui-accent left border plus a ~4% accent tint — never a solid fill block. <mark> inside __excerpt is Pagefind's own term highlighting, restyled to colour emphasis rather than a highlighter box. |
| .moss-footnotes | container | The document's endnote section, appended after the body by the renderer. Holds one <li id="fn-N"> per footnote in first-reference order, whatever depth the author wrote the definition at — a definition inside a blockquote or a list item is hoisted here too. Present only on pages that define at least one footnote. role="doc-endnotes" (DPUB-ARIA) names the region for assistive tech. |
| .moss-footnote-ref | instance | The in-body footnote marker: a superscript number linking down to its note. The number is first-reference order, not the author's label, so [^method] and [^1] both print as ordinals. A second marker for the same note takes id fnref-N-2, fnref-N-3, … so each has its own back-link. |
| .moss-footnote-backref | instance | The return arrow at the end of a note, linking back to the marker that sent the reader there. One per marker, so a note referenced twice ends with two arrows. A note nobody referenced has none. The arrow carries VARIATION SELECTOR-15 (︎) so mobile Chrome renders it as plain text rather than a coloured emoji. |
| .moss-sidenote | instance | A copy of an endnote, built in the browser by sidenotes.ts (never emitted by the build) and inserted immediately after its marker, which is aria-describedby-linked to it. Rendered only in a wide viewport's reserved gutter, where it floats beside the line that cites it; at narrow widths it stays display:none and the endnote section itself — lifted as the sticky bottom sheet — is the note's one presentation. |
| .moss-sidenote-number | instance | The ordinal at the head of a margin sidenote, repeating its marker's number. The one raised element inside the note, and what lets a reader tell two adjacent notes apart. |
| .moss-footnotes-title | instance | The endnote section's heading (localized en/zh-hans/zh-hant), inserted by sidenotes.ts — the pure renderer has no language. In flow always, not only on the lifted sheet, so the docked list and the sheet are the same pixels. Differentiated from the notes by type, not lines: the display face, small, muted, letter-spaced. |
| .moss-footnote-grab | instance | The lifted sheet's grabber: a full-width 24px touch strip drawing the standard pill, honest per iOS's rule because the sheet drags between two detents. A button (aria-label localized en/zh-hans/zh-hant), so the drag's destination — the expanded glossary — is equally reachable by tap, keyboard and screen reader. Hidden while the section rests in flow; its opacity rides the dock's --moss-sheet-away fade. |
| .moss-footnote-scroller | instance | The wrapper sidenotes.ts folds the endnote section's content into at init — layout-neutral in flow, the clipped scroll area on the lifted sheet. data-scrolly (present at the expanded detent only) is what re-enables native pan-y scrolling; below it the sheet itself owns every vertical gesture. |
| .moss-footnotes-cloned | state | The atomic licence, as a class: set by sidenotes.ts only when EVERY note gained a margin twin. Under the same screen-scoped media condition that renders the margin asides, it retires the endnote list from flow, tab order and the accessibility tree — the reader meets each note exactly once. One unclonable note and the class never lands. Print is outside the scope, so paper always gets the list. |
| .moss-footnotes-lifted | state | The endnote section as the bottom sheet: position: sticky; bottom: 0 plus a JS-driven height clip. The section never leaves flow — the peek clips to exactly the tapped note, dragging up expands to a 62vh glossary, and scrolling the page to the section's true place docks it back, chrome fading via --moss-sheet-away. One surface; nothing is cloned or re-parented. |
| .moss-footnote-landed | instance | The arrival wash, as a class: :target cannot reach a margin aside (no note id by design), so sidenotes.ts moves this class to whichever element the reader landed on — a margin aside on a #fn-N deep link, or the marker a backref returned them to. It fires only for an arrival the reader could not see coming: opening the sheet is not one, because the sheet shows the note. One element carries it at a time; same keyframes and reduced-motion contract as the li:target wash. |
| .container | chrome | The reading-width wrapper. It is the <article> on a page or post, and also the <nav class="main-nav container"> — one class, one measure, so the masthead lines up with the text under it. Site JS treats article.container as "the current document": immersive mode promotes its direct-child iframes, and the share card reads its data-share-cover. |
| .nav-content | chrome | The row inside the nav bar that holds .nav-left and .nav-right. It is the box the responsive nav measures itself against: when the two groups no longer fit on one line, nav-split.ts sets data-nav-split on this element and the links move to a second row. |
| .font-anchor | chrome | Positioning box for the reading-preferences control that sits at the end of an article's date line. Holds the trigger and the size pills; exists so the pills can be positioned against the trigger rather than the page. |
| .font-pill | instance | The reading-size control that opens from the font trigger. Each button carries data-scale; the one matching the current size additionally carries the bare class active. |
| .font-trigger | instance | The button that opens the reading-size pills. Its second class tracks the chosen size (size-std by default); moss's own theme no longer sizes the closed glyph by it (the trigger is one fixed size regardless of the reader's scale), but the co-class remains, so a theme can still restyle the trigger per size without reading state from JS. |
| .size-std | instance | Co-class on the font trigger reflecting the current reading size (size-std at the default). The default theme's closed glyph is one fixed size regardless of this class; it remains a hook for a theme that wants to show the active size on the closed control. |
| .cover-thumb | instance | The still frame stacked over a video cover. It is what the reader sees until they hover: card-video.ts fades this image out and starts the <video> underneath, and fades it back in on leave. Emitted only for video covers, inside .moss-card-cover or .moss-collection-cover. |
| .media-item | instance | One tile on the media-collection page. fullscreen.ts collects these in document order to build the lightbox playlist, so their order on the page is the order the arrows step through. |
| .lightbox-content | chrome | The stage of the media-collection lightbox. Holds all three players at once; fullscreen.ts unhides whichever one matches the opened item's data-type and leaves the others hidden. |
| .lightbox-image | instance | The lightbox's image player. Emitted empty and hidden; its src is filled in when an image item opens. |
| .lightbox-video | instance | The lightbox's video player. Emitted empty and hidden; paused and cleared when the lightbox closes so audio never outlives the overlay. |
| .lightbox-iframe | instance | The lightbox's embed surface, for media items that are an external player rather than a file. |
| .lightbox-title | instance | Caption line under the lightbox stage. Filled from the open item's data-title. |
| .lightbox-article-link | instance | The way back from a media tile to the article it appeared in. Its href is filled from the open item's data-article, and it is hidden when the item has none. |
| .lightbox-close | instance | Dismisses the media-collection lightbox. Escape does the same thing. |
| .lightbox-next | instance | Steps forward through the .media-item playlist, wrapping at the end. Carries lightbox-nav as well, which styles both arrows together. |
| .lightbox-prev | instance | Steps backward through the .media-item playlist, wrapping at the start. |
| .comments-toggle | instance | The <summary> that opens and closes the comment thread. Its <span> holds the count, which the client rewrites as comments arrive — so the span is a contract of its own, not decoration. |
| .comments-icon | instance | Speech-bubble icon inside the comments disclosure summary. |
| .comments-chevron | instance | Disclosure arrow inside the comments summary. Rotates with the <details> open state; the rotation is the only affordance saying the section collapses. |
| .comment-list | container | The top-level comment thread, rendered server-side at build time and then hydrated in place. New comments are appended here by the client rather than replacing the list, so server-rendered and live comments share one shape. |
| .comment-item | instance | One comment. Holds a .comment-header, a .comment-body, and — if it has replies — a nested .comment-replies. The data-comment-* pair is how the client matches a live comment to the one already on the page instead of rendering it twice. |
| .comment-header | instance | Attribution row of a single comment: who wrote it, when, and where it came from. |
| .comment-body | instance | The comment text itself, separated from the attribution header so the two can be styled independently. |
| .comment-author | instance | The commenter's name, linked to the URL they supplied. Always carries rel=nofollow ugc — the link is reader-supplied content, not an endorsement by the site. | | `.comment-date` | instance | Publication time of a comment, as a `<time>` element carrying a machine-readable `datetime`. | | `.comment-source-link` | instance | Link back to where a syndicated comment originated, for comments moss did not receive directly. | | `.comment-replies` | container | Nested replies under a comment, same shape as `.comment-list`. Emitted only when a comment has replies; the client creates one on demand when the first reply arrives. | | `.comment-reply-btn` | instance | Moves the comment form under this comment so the reply is written where it will appear. Emitted only for comments moss can reply to; a syndicated comment gets a link out to its own platform instead. | | `.review-colophon` | standalone | Footer block of a review page carrying the details of the work being reviewed. A `<footer>` because it describes the subject rather than continuing the argument. | | `.review-colophon-details` | instance | Container for the reviewed work's identifying fields inside the colophon. | | `.review-biblio` | instance | Full bibliographic citation of the reviewed work, formatted as one line. | | `.review-rating` | instance | The reviewer's own rating of the work. | | `.review-community-rating` | instance | Aggregate rating carried over from the source catalogue, kept visually distinct from the reviewer's own so the two are never read as one judgement. | | `.review-links` | instance | Navigation to the reviewed work elsewhere — catalogue entries, purchase pages, the publisher. | | `.review-sep` | instance | Separator between review links. An element rather than a `::before` so it can be hidden when links wrap. | | `.review-colophon-title` | instance | Title of the work being reviewed — not the title of the review itself, which is the page heading. | | `.review-colophon-subtitle` | instance | Subtitle of the reviewed work, rendered only when one is present. | | `.review-colophon-identity` | instance | The reviewed work's identifier (ISBN, DOI or equivalent), which is what makes a review resolvable to a specific edition. | | `.page-wrapper` | container | Outermost wrapper of a generated media-collection page. | | `.main-content` | instance | Primary content column of a media-collection page, inside the page wrapper. | | `.media-grid` | instance | The grid of media items on a media-collection page. | | `.media-overlay` | instance | Caption overlay drawn over a media thumbnail, typically revealed on hover or focus. | | `.media-title` | instance | Title of a single media item, inside its overlay. | | `.lightbox` | standalone | Full-screen viewer for a media collection. Ships `hidden` and `tabindex=`-1 so it is out of the tab order until opened. |
| .lightbox-caption | instance | Caption area of the lightbox, describing the item currently shown. |
| .lightbox-nav | instance | Previous/next control in the lightbox. Carries a direction co-class (lightbox-prev / lightbox-next) and always an aria-label, since the visible glyph is a chevron. |
| .latest-sidebar | standalone | Sidebar listing the most recent entries. A <nav> because it is a navigational aid, not part of the page's argument. |
| .sidebar-more | instance | Link from the latest-entries sidebar to the full listing. |
| .active | instance | Bare state co-class marking the currently-selected item in a set — the current page in .nav-links, the current size in .font-pill. Style it scoped to its container (.nav-links .active), never on its own. |
| .has-sidebar-layout | instance | Marks a page laid out with a sidebar, so the main column can reserve room for it without the sidebar having rendered yet. |
| .wikilink | instance | Marks a link that came from [[wikilink]] syntax rather than a markdown link, so a theme can distinguish internal cross-references from ordinary links. |
| .moss-term-role | instance | Section heading on a term page (e.g. /people/
| .moss-place-breadcrumb | instance | Ancestor trail on a place page (e.g. /places/.breadcrumb-segment/.breadcrumb-separator classes. Absent for a root place with no gazetteer parent, and for every non-place term. |
| .moss-place-children | instance | Direct child places on a place page, each with its roll-up-inclusive member count. Absent for a leaf place with no children, and for every non-place term. |
| .moss-place-line | instance | The automatic place line under a page's byline, generated from location: — every declared place, linked to its term page. Absent when location: is unset, or the site declares no place-typed kind. No opt-out: this is generated chrome with no authored equivalent. |
| .moss-place-map | instance | Offline SVG map on a place term page or explicit style:map embed. Geography and privacy precision come from .moss/places.toml; no browser network request is made. |
| .moss-place-map-frame | container | Placement wrapper for an explicit map embed. Carries the standard width, alignment and size attributes while the semantic map figure remains self-contained. |
| .moss-place-map-caption | instance | Optional caption below an explicitly embedded place map. |
| .moss-place-locator | container | Compact sparse map after an authored page's location line when [site].locator = "align-right"; collapses into the reading flow on narrow screens. |
| .moss-places-viewport | instance | The focusable, pannable region the explorer lays over the static figure's box once the world map has loaded. Captures drag, wheel, pinch and arrow-key gestures; absent (the static SVG alone) until then or if the data fetch fails. |
| .moss-places-world | instance | Carries the world's own decoded raster (raster.ts's splitMapSvg/rasterizeOrFallback, built from the fetched world.svg) plus its live, unfiltered rivers overlay, and the CSS transform the camera drives. |
| .moss-places-world-surface | instance | The world layer's own decoded raster — an <img>, or (a browser lacking Blob/HTMLImageElement.decode() support) the live, unrasterised <svg> itself. Re-decoded at a sharper size on settle, up to a capped zoom past which it is left to go soft under whatever regional tiles cover that area. |
| .moss-places-rivers | instance | A live, unfiltered overlay of just the [data-map-layer="rivers"] group, extracted from the world or a regional tile's own fetched SVG (raster.ts's splitMapSvg) so --moss-place-river-scale keeps working — a rasterised sibling has no access to the page's own custom properties. One per moss-places-world and one per moss-places-tile that actually drew a river. |
| .moss-places-tiles | instance | Regional detail layer above moss-places-world: once the camera's screen scale passes the world ceiling, the tiles tiles.json lists for the current view are fetched, cached and positioned here at their own 10° cell. |
| .moss-places-tile | instance | One fetched, decoded regional tile: a positioned wrapper (tiles.ts's TileLayer) carrying the tile's own raster image and, if the tile drew one, its own moss-places-rivers overlay. |
| .moss-places-labels | container | Decorative place-name layer, above the map and below moss-places-markers. Rebuilt on every camera settle (skipped mid-gesture, matching moss-places-world's own [data-gesture] window) from labels.json's cities, mountain ranges, peaks and rivers, greedily placed by priority within an area budget and never overlapping another label, a marker, the controls or the card row. |
| .moss-places-label | instance | One placed label's text. hidden when the greedy placement pass this settle did not have room for it — present in the DOM either way, so repeated camera settles never rebuild the underlying text/measurement work. |
| .moss-places-label-dot | instance | A city label's own anchor point, shown only when its name text had to move aside from a work marker sitting on the exact place — hidden (the marker IS the dot) when the label sits beside a marker whose own place it names, and hidden along with the label itself when dropped entirely. |
| .moss-places-markers | instance | Marker and ring layer, above the map layers. Rebuilt on every camera settle from the works currently in scope and view. |
| .moss-places-marker | instance | One button per work, or per cluster of works mergeByProximity merges at the current zoom. Clicking a single-work marker selects it; clicking a separable cluster zooms to separate it; clicking a cluster that stays merged at the detail ceiling blooms it into a ring instead. |
| .moss-places-ring-leg | instance | A hairline from a bloomed ring's anchor to one of its own moss-places-ring-dot buttons, evenly spaced clockwise from 12 o'clock. |
| .moss-places-ring-dot | instance | One real, individually-clickable button per work in a bloomed ring — a coincident cluster too close to ever separate by zooming, rendered as a small circle of dots instead of staying a single merged marker. Row order matches the scoped card row, both derived from the same work order. |
| .moss-places-controls | container | Top-right floating control stack: the zoom capsule and the reset-to-cover circle, sharing one glass material. |
| .moss-places-capsule | container | The two-cell zoom pill. Carries the glass material and the capsule's own rounded ends; its two moss-places-control cells are transparent so the capsule's background shows through, divided by one hairline. |
| .moss-places-control | instance | One control button: a 36px visible circle with a 44px hit area (an inset pseudo-element extends it without growing the painted size), round focus/hover/pressed states following that shape. |
| .moss-places-chip | container | Top-left floating breadcrumb scope chip, sharing moss-places-controls' own glass material. Shows the trail from every work down to the current scope (or the selected work, or an open ring's own member count) and is the map's one hierarchy control: an earlier crumb widens back out, the terminal crumb's own chevron digs into its children. |
| .moss-places-chip-trail | instance | Flex row of moss-places-chip-crumb/moss-places-chip-sep pairs, rebuilt whole on every scope, selection or ring change. |
| .moss-places-chip-crumb | instance | One crumb: a <button> when clicking it widens the scope (or opens the terminal crumb's own menu), a plain <span> for a leaf terminal crumb (a selected work, an open ring's count, or a place with no children). display: flex; align-items: center keeps every crumb's text on the same baseline as its neighbouring moss-places-chip-sep, regardless of which element is a real button. |
| .moss-places-chip-sep | instance | The › between two crumbs, decorative (aria-hidden). |
| .moss-places-chip-chevron | instance | Inline-SVG chevron inside the terminal crumb, present only when places lie under the current scope; flips 180° when its own crumb's aria-expanded is true. |
| .moss-places-chip-collapsible | instance | Wraps every crumb between the trail's first and terminal one. Always in the DOM; places-explorer.css hides it below a phone-width breakpoint, where moss-places-chip-ellipsis shows in its place — a CSS-only swap, nothing JS toggles on resize, except data-expanded, which moss-places-chip-ellipsis itself sets. |
| .moss-places-chip-ellipsis | instance | The phone-width stand-in for moss-places-chip-collapsible, hidden above that breakpoint. A real button, not decorative text: activating it sets its own aria-expanded and toggles moss-places-chip-collapsible's data-expanded, so every crumb the phone width would otherwise hide stays reachable by keyboard or touch. |
| .moss-places-chip-menu | container | The terminal crumb's dig-down menu: the current scope's own direct children, sharing the chip's glass material. Opens on the terminal crumb's click, closes on Escape, an outside click, or choosing an item; arrow keys move a roving tabindex between moss-places-chip-menu-items. |
| .moss-places-chip-menu-item | instance | One child place, sorted by work count descending then name (the same order scope.ts's childrenOf already gives a place term page's own children list). Hovering or focusing it exempts its own works from the marker layer's dimming attribute — the same one a bloomed ring uses — and dims the rest; choosing it narrows the scope to that place. |
| .moss-places-chip-menu-count | instance | A menu item's own locale-formatted work count, in parentheses. |
| .moss-places-cards | container | The horizontal row of works currently in scope and in view, floating along the bottom of the map. Each child is a moss-card, sorted by date descending then title. |
| .moss-places-card-select | instance | Wraps a moss-places-cards card's own moss-card-row: the whole card's click target, toggling its moss-places-card-detail open or closed. |
| .moss-places-card-detail | instance | A selected moss-places-cards card's own expand-in-place detail: description, place names, companion links and a link to the article. Collapsed (and inert) on every other card. |
| .moss-card-meta-author | instance | The author names on a collapsed moss-places-cards card's one-line meta, joined with the language's list separator. It shrinks and is ellipsised when the line is too long; the date beside it never is. |
| .moss-card-meta-date | instance | The date on a collapsed moss-places-cards card's meta line. It carries its own leading no-break-space, middle dot, no-break-space separator when an author precedes it, and never shrinks or wraps. |
| .moss-places-chip-scope | instance | The two-segment "This article | All articles" switch that replaces the breadcrumb trail on an article's own map. The current segment carries aria-current. |
| .moss-places-chip-scope-option | instance | One segment of the moss-places-chip-scope switch. |
| .immersive-fullscreen-btn | standalone | The expand control moss adds over an embedded iframe (a places map or any embed that goes fullscreen); inside fullscreen it is the exit control, a solid 36px circle with the same shadow as the map's own zoom controls so it reads over any map colour. |
| .moss-places-card-read | instance | Link to the work's own article, inside an expanded card's detail region. |
| .moss-places-status | standalone | Visually-hidden polite live region announcing scope and selection changes — never pan or zoom, and never a visible status line. |
| .moss-places-embed-frame | instance | The lazy-hydrated iframe embed.ts creates behind a style:map/locator poster once it nears the viewport (or on tap, under Save-Data). Transparent and non-interactive until it cross-fades in. |
| .moss-places-embed-frame--settled | instance | Added once the iframe's own explorer posts back ready: cross-fades it over the static poster. Never added at all when the fetch fails or times out — the poster stays exactly as it was. |
| .moss-places-coop-hint | instance | map.ts's one-time nudge toward the zoom modifier: appended to the viewport the first time a reader wheels a COOPERATIVE (collapsed-embed) map without it held, since a bare wheel there deliberately does nothing — gestures.ts leaves it for the page's own scroll. Never appears on the full explorer page, which has no competing scroll to defer to. |
| .moss-places-coop-hint--visible | instance | Added one frame after the hint mounts (so its own opacity transition runs) and removed a couple of seconds later as the hint auto-dismisses — never left present once dismissed. |