autumn-web 0.10.0

An opinionated, convention-over-configuration web framework for Rust
Documentation
/* Social widgets (`widgets-social`). The server joins this file to
   autumn-widgets.css only when the feature is on (#3408). */

/* ── Infinite feed (autumn-feed) ───────────────────────────────────────────── */

.autumn-feed {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.autumn-feed__sentinel {
    display: flex;
    justify-content: center;
    padding: var(--space-4) 0;
}

.autumn-feed__more {
    display: inline-block;
    padding: var(--space-2) var(--space-5);
    color: var(--primary);
    font-weight: var(--font-weight-medium);
    font-size: 0.9375rem;
    text-decoration: none;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.autumn-feed__more:hover {
    border-color: var(--primary);
}

.autumn-feed__more:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ── Reaction controls (autumn-reaction-*, issue #1362) ───────────────────── */

/* The `role="group"` container holds one no-JS POST form per direction with
   the aggregate between them. A column stacks up / count / down into the
   familiar vote-arrow strip; `likes` mode simply renders one form and the
   count, so the same rule serves both. */
.autumn-reaction-controls {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.125rem;
}

/* Each direction is its own form so it can be submitted without JS; strip the
   default block-level margin so the arrows sit tight against the count. */
.autumn-reaction {
    display: inline-flex;
    margin: 0;
}

/* The direction modifiers carry no geometry of their own -- they exist as
   styling/targeting hooks so an app can re-colour a single direction (e.g. a
   warm upvote, a cool downvote) without forking the base rules. */
.autumn-reaction-up {
    color: inherit;
}

.autumn-reaction-down {
    color: inherit;
}

.autumn-reaction-like {
    color: inherit;
}

/* Borderless icon button: the glyph is the affordance, so no chrome until
   hover/focus. `color: inherit` keeps the resting arrow the same weight as
   surrounding text; `--text-muted` would drop below 3:1 on `--surface`. */
.autumn-reaction-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.125rem 0.375rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background-color: transparent;
    color: var(--text);
    font: inherit;
    line-height: 1;
    cursor: pointer;
}

.autumn-reaction-button:hover {
    background-color: var(--surface);
    border-color: var(--border);
}

.autumn-reaction-button:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* The viewer's own reaction (`aria-pressed="true"`). Colour is a redundant
   cue only -- `aria-pressed` is the machine-readable state -- so this never
   has to carry the meaning alone. */
.autumn-reaction-active {
    color: var(--primary);
    border-color: var(--primary);
}

/* The aggregate, announced via `aria-live="polite"` after an htmx swap.
   `tabular-nums` stops the strip from reflowing as the score changes width. */
.autumn-reaction-count {
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
    color: var(--text);
}

/* ── Comment threads (autumn-comment-*, issue #1367) ──────────────────────── */

/* The region landmark wrapping the whole thread. It is also the htmx swap
   target, so it must not itself be positioned or transformed -- an outerHTML
   swap replaces this element wholesale. */
.autumn-comments {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* Every nesting level is an `<ol>`: the order is meaningful (chronological),
   and a list is what a screen reader announces the depth of. The list markers
   are suppressed; the indent guide below is the visual cue instead. */
.autumn-comment-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* A nested level indents behind a rule, which is what makes depth legible
   without a per-level class (the widget renders arbitrarily deep). The
   `border-inline-start` is logical, so it flips for RTL locales. */
.autumn-comment .autumn-comment-list {
    margin-block-start: var(--space-3);
    padding-inline-start: 0.875rem;
    border-inline-start: 2px solid var(--border);
}

.autumn-comment {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.autumn-comment-meta {
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.autumn-comment-author {
    font-weight: var(--font-weight-semibold);
    color: var(--text);
}

/* `tabular-nums` keeps a column of timestamps from shifting as digits change. */
.autumn-comment-time {
    font-variant-numeric: tabular-nums;
}

/* `overflow-wrap` rather than `word-break`: a pasted URL has to wrap, but
   ordinary prose must still break on spaces. */
.autumn-comment-body {
    color: var(--text);
    overflow-wrap: anywhere;
}

.autumn-comment-body p {
    margin: 0 0 var(--space-2);
}

.autumn-comment-body p:last-child {
    margin-bottom: 0;
}

/* `<details>`/`<summary>` gives progressive disclosure with no JavaScript at
   all -- the reply form is in the DOM and reachable by keyboard whether or not
   htmx (or any script) loaded. */
.autumn-comment-reply {
    font-size: var(--font-size-sm);
}

.autumn-comment-reply-toggle {
    cursor: pointer;
    color: var(--primary);
    width: fit-content;
}

.autumn-comment-reply-toggle:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.autumn-comment-form {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: var(--space-2) 0 0;
}

/* The label doubles as the visible prompt, so it is not visually hidden -- a
   placeholder alone is not an accessible name. */
.autumn-comment-label {
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.autumn-comment-input {
    width: 100%;
    padding: var(--space-2);
    border: 1px solid var(--control-border);
    border-radius: var(--radius);
    background-color: var(--surface);
    color: var(--text);
    font: inherit;
    resize: vertical;
}

.autumn-comment-input:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}

.autumn-comment-submit {
    align-self: flex-start;
    padding: 0.375rem var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
    color: var(--text);
    font: inherit;
    cursor: pointer;
}

.autumn-comment-submit:hover {
    border-color: var(--primary);
}

.autumn-comment-submit:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.autumn-comments-empty,
.autumn-comments-prompt {
    margin: 0;
    color: var(--text-muted);
}

/* A rejected comment, announced via `role="alert"`. Colour is a redundant cue
   only -- the role is the machine-readable state. */
.autumn-comments-error {
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--danger);
    border-radius: var(--radius);
    color: var(--danger);
}