/* =============================================================================
   ATRIUM · 03 · COMPONENT LIBRARY
   =============================================================================
   Every reusable object in the product, designed once and reused everywhere.
   A component that needs to differ on one page is a variant here, never a
   page-level override.

   THE FIVE LAWS THIS LIBRARY IS BUILT ON
   1. LIGHT, NOT LINES. Rank is luminance and elevation. A hairline appears
      only where two surfaces of equal height genuinely touch.
   2. A PRESS IS PHYSICAL. Controls travel 1px into the page and give up
      their shadow. Nothing scales — scaling resamples text and media
      mid-gesture, which is the cheapest-looking thing an interface can do.
   3. ONE FOCUS RING. A 2px Porphyry outline at 2px offset, drawn with
      `outline` so it never enters layout, never fights the element's own
      shadow, and is identical on every control in the product.
   4. CONCENTRIC CORNERS. An inner radius equals its outer radius minus the
      gap between them. Corners that do not share a centre read as
      carelessness.
   5. CIRCLES BELONG TO PEOPLE. Avatars are the only true circles; pills are
      reserved for the few controls that must read as tokens.

   CONTENTS
     1. Card & vitrine          9. Badges, seals, counts
     2. Buttons                10. Tags & chips
     3. Fields & forms         11. Progress
     4. Selection controls     12. Tooltip
     5. Search                 13. Avatar
     6. Menu / dropdown        14. Lists & rows
     7. Modal, sheet & dialog  15. Table & swatches
     8. Tabs & segments        16. Alert · Toast · Skeleton · Empty · Motion

   CONTRACTS: class names below are the API the PHP partials and JS speak.
   The custom properties --btn-bg / --btn-ink are part of that API (post
   modals set them inline for brand share buttons).
   ========================================================================== */

/* =============================================================================
   1 · CARD & VITRINE
   -----------------------------------------------------------------------------
   A card is lit plaster standing slightly proud of the canvas: a lighter
   surface and a soft mineral shadow, never a border. The vitrine is the
   case user media sits in — the only saturated thing on a screen.
   ========================================================================== */
.v-card {
    --card-pad: var(--at-s5);
    position: relative;
    border-radius: var(--at-r-lg);
    background-color: var(--at-surface);
    box-shadow: var(--at-edge), var(--at-shadow-sm);
    overflow: hidden;
}

.v-card--raised {
    background-color: var(--at-surface-raised);
    box-shadow: var(--at-edge), var(--at-shadow-md);
}

.v-card--padded { padding: var(--card-pad); }

/* Only cards that *do* something respond to the pointer, and they rise
   toward the light rather than growing. */
.v-card--interactive {
    cursor: pointer;
    transition: box-shadow var(--at-t-base) var(--at-ease-out),
                transform var(--at-t-base) var(--at-ease-out),
                background-color var(--at-t-base) var(--at-ease-out);
}

.v-card--interactive:hover {
    transform: translateY(-2px);
    box-shadow: var(--at-edge), var(--at-shadow-md);
}

.v-card--interactive:active {
    transform: translateY(0);
    box-shadow: var(--at-edge), var(--at-shadow-xs);
    transition-duration: var(--at-t-instant);
}

.v-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--at-s3);
    padding: var(--at-s4) var(--card-pad);
    border-bottom: 1px solid var(--at-hairline);
}

.v-card__title {
    margin: 0;
    font-size: var(--at-text-lg);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-title);
    color: var(--at-ink);
}

.v-card__body { padding: var(--card-pad); }

.v-card__footer {
    display: flex;
    align-items: center;
    gap: var(--at-s2);
    padding: var(--at-s3) var(--card-pad);
    border-top: 1px solid var(--at-hairline);
}

/* --- The vitrine ---------------------------------------------------------- */
.v-vitrine {
    position: relative;
    overflow: hidden;
    /* Concentric with the card it sits inside. */
    border-radius: calc(var(--at-r-lg) - var(--at-s2));
    background-color: var(--at-surface-sunken);
}

.v-vitrine > img,
.v-vitrine > video {
    display: block;
    width: 100%;
    max-height: 80vh;
    object-fit: cover;
}

/* The functional veil — spoiler, age gate, paywall. The one sanctioned
   scrim in the product. The blur itself is applied via the `.is-veiled`
   contract class in atrium.product.css (post.js removes it to reveal); the
   BEM `--veiled` variant that used to live here was defined but never used
   in any markup, so it was pure duplication and is gone. */
.v-veil {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--at-s1);
    padding: var(--at-s5);
    border: 0;
    background: var(--at-scrim);
    color: #fff;
    text-align: center;
    cursor: pointer;
    transition: background-color var(--at-t-base) var(--at-ease-out),
                opacity var(--at-t-slow) var(--at-ease-in);
}

.v-veil:hover { background: var(--at-scrim-strong); }

.v-veil__title {
    font-size: var(--at-text-lg);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-title);
}

.v-veil__text {
    max-width: 34ch;
    font-size: var(--at-text-sm);
    line-height: var(--at-leading-snug);
    opacity: 0.88;
}

/* A small factual tag over media (GIF, duration) — never decorative. */
.v-vitrine__tag {
    position: absolute;
    inset-inline-start: var(--at-s3);
    inset-block-end: var(--at-s3);
    padding: 0.15rem 0.45rem;
    border-radius: var(--at-r-xs);
    background: var(--at-scrim-strong);
    color: #fff;
    font-size: var(--at-text-xs);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-caps);
    line-height: 1.5;
}

/* =============================================================================
   2 · BUTTONS
   -----------------------------------------------------------------------------
   One plate, six voices. The primary is the single act of the room and
   appears at most once per view. Every button answers within --at-t-instant
   and presses INTO the page (law 2).
   ========================================================================== */
.v-btn {
    --btn-bg: transparent;
    --btn-ink: var(--at-ink);
    --btn-shadow: none;

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--at-s2);
    min-height: var(--at-control-h);
    padding: 0 var(--at-s5);
    border: 0;
    border-radius: var(--at-r-md);
    background-color: var(--btn-bg);
    color: var(--btn-ink);
    box-shadow: var(--btn-shadow);
    font-family: inherit;
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-body);
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--at-t-fast) var(--at-ease-out),
                color var(--at-t-fast) var(--at-ease-out),
                box-shadow var(--at-t-fast) var(--at-ease-out),
                translate var(--at-t-instant) var(--at-ease-out);
}

/* The hand always gets 44px even when the ink is smaller. */
.v-btn::after {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    width: max(100%, var(--at-hit));
    height: max(100%, var(--at-hit));
    transform: translate(-50%, -50%);
}

.v-btn:hover { color: var(--btn-ink); }

/* Law 2: a press is a press, not a shrink. */
.v-btn:active {
    translate: 0 1px;
    box-shadow: none;
}

/* Law 3: one ring, everywhere. */
.v-btn:focus-visible {
    outline: 2px solid var(--at-accent);
    outline-offset: 2px;
}

.v-btn:disabled,
.v-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    translate: none;
    box-shadow: none;
    pointer-events: none;
}

/* --- Voices --------------------------------------------------------------- */
/* The one act. */
.v-btn--primary {
    --btn-bg: var(--at-accent);
    --btn-ink: var(--at-accent-contrast);
    --btn-shadow: var(--at-shadow-xs);
}
.v-btn--primary:hover  { --btn-bg: var(--at-accent-hover); --btn-shadow: var(--at-shadow-sm); }
.v-btn--primary:active { --btn-bg: var(--at-accent-active); }

/* The everyday working plate. */
.v-btn--quiet {
    --btn-bg: var(--at-surface-raised);
    --btn-ink: var(--at-ink);
    --btn-shadow: var(--at-edge), var(--at-shadow-xs);
}
.v-btn--quiet:hover { --btn-bg: var(--at-surface-hover); }

/* Bare ink — toolbars and tertiary actions. */
.v-btn--ghost {
    --btn-bg: transparent;
    --btn-ink: var(--at-ink-secondary);
}
.v-btn--ghost:hover {
    --btn-bg: var(--at-surface-hover);
    --btn-ink: var(--at-ink);
}

/* Destructive actions whisper first and only commit under the pointer. */
.v-btn--danger {
    --btn-bg: var(--at-danger-soft);
    --btn-ink: var(--at-danger);
}
.v-btn--danger:hover {
    --btn-bg: var(--at-danger);
    --btn-ink: #fff;
}
.v-btn--danger:focus-visible { outline-color: var(--at-danger); }

/* Verdigris — the economy only: buy, upgrade, withdraw. */
.v-btn--gilt {
    --btn-bg: var(--at-gilt);
    --btn-ink: var(--at-gilt-contrast);
    --btn-shadow: var(--at-shadow-xs);
}
.v-btn--gilt:hover { --btn-bg: var(--at-gilt-bright); --btn-shadow: var(--at-shadow-sm); }
.v-btn--gilt:focus-visible { outline-color: var(--at-gilt); }

/* --- Sizes & shapes -------------------------------------------------------- */
.v-btn--sm {
    min-height: var(--at-control-h-sm);
    padding: 0 var(--at-s3);
    font-size: var(--at-text-xs);
    border-radius: var(--at-r-sm);
}

.v-btn--lg {
    min-height: var(--at-control-h-lg);
    padding: 0 var(--at-s6);
    font-size: var(--at-text-md);
}

.v-btn--pill  { border-radius: var(--at-r-pill); }
.v-btn--block { display: flex; width: 100%; }

.v-btn--icon {
    width: var(--at-control-h);
    min-height: var(--at-control-h);
    padding: 0;
    border-radius: var(--at-r-pill);
}

.v-btn--icon.v-btn--sm { width: var(--at-control-h-sm); min-height: var(--at-control-h-sm); }

/* Working: the label leaves, the spinner takes its place, the box does not
   move (a button that resizes mid-submit loses the pointer). */
.v-btn.is-loading {
    color: transparent !important;
    pointer-events: none;
}

.v-btn.is-loading::before {
    content: "";
    position: absolute;
    width: 1rem;
    height: 1rem;
    border: 2px solid var(--btn-ink);
    border-inline-end-color: transparent;
    border-radius: 50%;
    animation: v-spin 0.7s linear infinite;
}

@keyframes v-spin { to { transform: rotate(360deg); } }

/* =============================================================================
   3 · FIELDS & FORMS
   -----------------------------------------------------------------------------
   A field is cut into the surface and rises to meet you: sunken at rest,
   plaster-raised and ringed in Porphyry while it holds the caret.
   ========================================================================== */
.v-field { display: flex; flex-direction: column; gap: var(--at-s2); }

.v-label {
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-medium);
    color: var(--at-ink-secondary);
}

.v-input,
.v-select,
.v-textarea {
    display: block;
    width: 100%;
    min-height: var(--at-control-h);
    padding: 0 var(--at-s4);
    border: 1px solid transparent;
    border-radius: var(--at-r-md);
    background-color: var(--at-surface-sunken);
    color: var(--at-ink);
    font-family: inherit;
    font-size: var(--at-text-md);
    letter-spacing: var(--at-tracking-body);
    line-height: var(--at-leading-normal);
    transition: background-color var(--at-t-base) var(--at-ease-out),
                border-color var(--at-t-base) var(--at-ease-out),
                box-shadow var(--at-t-base) var(--at-ease-out);
}

.v-textarea {
    min-height: calc(var(--at-control-h) * 2.4);
    padding: var(--at-s3) var(--at-s4);
    resize: vertical;
}

/* The select never wore its own chevron — it fell back to the OS control,
   which is the one part of a form you cannot theme. It has one now, drawn
   in the muted ink and mirrored for RTL by background-position. */
.v-select {
    appearance: none;
    -webkit-appearance: none;
    padding-inline-end: var(--at-s8);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%238C8779' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--at-s4) center;
    background-size: 12px 8px;
}

[dir="rtl"] .v-select { background-position: left var(--at-s4) center; }

[data-theme="dark"] .v-select,
[data-theme="night"] .v-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23847D6D' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.v-input::placeholder,
.v-textarea::placeholder {
    color: var(--at-ink-muted);
    opacity: 1;
}

.v-input:hover,
.v-select:hover,
.v-textarea:hover { background-color: var(--at-surface-hover); }

.v-input:focus,
.v-select:focus,
.v-textarea:focus {
    outline: none;
    background-color: var(--at-surface-raised);
    border-color: var(--at-accent);
    box-shadow: 0 0 0 3px var(--at-focus-ring);
}

.v-input:disabled,
.v-select:disabled,
.v-textarea:disabled {
    color: var(--at-ink-muted);
    cursor: not-allowed;
    opacity: 0.7;
}

.v-input[aria-invalid="true"],
.v-input.is-invalid,
.v-textarea.is-invalid { border-color: var(--at-danger); }

.v-input.is-invalid:focus,
.v-textarea.is-invalid:focus { box-shadow: 0 0 0 3px var(--at-danger-soft); }

.v-hint  { font-size: var(--at-text-xs); color: var(--at-ink-muted); }
.v-error { font-size: var(--at-text-xs); color: var(--at-danger); }

/* A field carrying a leading mark or a trailing control. */
.v-field__wrap { position: relative; display: flex; align-items: center; }

.v-field__wrap .v-field__icon {
    position: absolute;
    inset-inline-start: var(--at-s4);
    display: flex;
    color: var(--at-ink-muted);
    pointer-events: none;
}

.v-field__wrap .v-field__icon ~ .v-input { padding-inline-start: var(--at-s8); }

.v-field__trail {
    position: absolute;
    inset-inline-end: var(--at-s1);
    display: flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--at-control-h) - var(--at-s2));
    height: calc(var(--at-control-h) - var(--at-s2));
    border: 0;
    border-radius: var(--at-r-pill);
    background: transparent;
    color: var(--at-ink-muted);
    cursor: pointer;
    transition: color var(--at-t-fast) var(--at-ease-out),
                background-color var(--at-t-fast) var(--at-ease-out);
}

.v-field__trail:hover {
    background-color: var(--at-surface-hover);
    color: var(--at-ink);
}

/* =============================================================================
   4 · SELECTION CONTROLS — checkbox, radio, switch
   -----------------------------------------------------------------------------
   Small objects with real state. Unchecked they are an empty well with a
   hairline lip; checked they fill with Porphyry and the mark is struck in
   the contrast ink.
   ========================================================================== */
.v-check,
.v-radio {
    appearance: none;
    -webkit-appearance: none;
    display: inline-grid;
    place-content: center;
    width: 1.25rem;
    height: 1.25rem;
    margin: 0;
    border: 1.5px solid var(--at-hairline-strong);
    background-color: var(--at-surface-raised);
    cursor: pointer;
    transition: background-color var(--at-t-fast) var(--at-ease-out),
                border-color var(--at-t-fast) var(--at-ease-out);
}

.v-check { border-radius: var(--at-r-xs); }
.v-radio { border-radius: 50%; }

.v-check:hover,
.v-radio:hover { border-color: var(--at-ink-faint); }

.v-check:checked,
.v-radio:checked {
    background-color: var(--at-accent);
    border-color: var(--at-accent);
}

.v-check:checked::before {
    content: "";
    width: 0.625rem;
    height: 0.375rem;
    border-inline-start: 2px solid var(--at-accent-contrast);
    border-block-end: 2px solid var(--at-accent-contrast);
    transform: rotate(-45deg) translateY(-1px);
}

.v-radio:checked::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--at-accent-contrast);
}

.v-check:focus-visible,
.v-radio:focus-visible {
    outline: 2px solid var(--at-accent);
    outline-offset: 2px;
}

/* An option worn as a chip: the control and its label are one target, which
   is what a radio in a row of three should have been all along. */
.v-optionchip {
    display: inline-flex;
    align-items: center;
    gap: var(--at-s2);
    min-height: var(--at-control-h);
    padding: 0 var(--at-s4);
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface-sunken);
    color: var(--at-ink-secondary);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-medium);
    cursor: pointer;
    transition: background-color var(--at-t-fast) var(--at-ease-out),
                color var(--at-t-fast) var(--at-ease-out);
}

.v-optionchip:hover { background-color: var(--at-surface-hover); color: var(--at-ink); }

.v-optionchip:has(input:checked) {
    background-color: var(--at-accent-soft);
    color: var(--at-accent-ink);
    font-weight: var(--at-weight-semibold);
}

.v-optionchip:has(input:focus-visible) {
    outline: 2px solid var(--at-accent);
    outline-offset: 2px;
}

/* --- Switch: a physical object with give ----------------------------------- */
.v-switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
}

.v-switch input {
    position: absolute;
    opacity: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    cursor: pointer;
}

.v-switch__track {
    width: 2.75rem;
    height: 1.625rem;
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface-sunken);
    box-shadow: inset 0 0 0 1px var(--at-hairline);
    transition: background-color var(--at-t-base) var(--at-ease-out);
}

.v-switch__track::before {
    content: "";
    display: block;
    width: 1.375rem;
    height: 1.375rem;
    margin: 0.125rem;
    border-radius: 50%;
    background: var(--at-surface-raised);
    box-shadow: var(--at-shadow-sm);
    transition: transform var(--at-t-base) var(--at-ease-spring);
}

.v-switch input:checked + .v-switch__track {
    background-color: var(--at-accent);
    box-shadow: none;
}

.v-switch input:checked + .v-switch__track::before { transform: translateX(1.125rem); }
[dir="rtl"] .v-switch input:checked + .v-switch__track::before { transform: translateX(-1.125rem); }

.v-switch input:focus-visible + .v-switch__track {
    outline: 2px solid var(--at-accent);
    outline-offset: 2px;
}

/* =============================================================================
   5 · SEARCH
   ========================================================================== */
.v-search {
    position: relative;
    flex: 1 1 auto;
    max-width: 22rem;
}

.v-search .v-input {
    border-radius: var(--at-r-pill);
    padding-inline-start: var(--at-s8);
    min-height: calc(var(--at-control-h) - 0.25rem);
}

.v-search__icon {
    position: absolute;
    top: 50%;
    inset-inline-start: var(--at-s4);
    transform: translateY(-50%);
    color: var(--at-ink-muted);
    pointer-events: none;
}

.v-search__panel {
    position: absolute;
    top: calc(100% + var(--at-s2));
    inset-inline: 0;
    z-index: var(--at-z-dropdown);
    max-height: 60vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--at-s2);
    border-radius: var(--at-r-lg);
    background-color: var(--at-surface-raised);
    box-shadow: var(--at-edge), var(--at-shadow-lg);
}

.v-search__panel:empty { display: none; }

.v-search__empty {
    padding: var(--at-s7) var(--at-s4);
    text-align: center;
    color: var(--at-ink-muted);
    font-size: var(--at-text-sm);
}

/* =============================================================================
   6 · MENU / DROPDOWN / CONTEXT MENU
   -----------------------------------------------------------------------------
   One temporary surface grammar for dropdown menus, context menus and the
   contents of action sheets. The surface itself never animates position —
   positioning belongs to the host (Bootstrap), light belongs to us.
   ========================================================================== */
.v-menu {
    min-width: 13rem;
    padding: var(--at-s2);
    border-radius: var(--at-r-lg);
    background-color: var(--at-surface-raised);
    box-shadow: var(--at-edge), var(--at-shadow-lg);
}

.v-menu__item {
    display: flex;
    align-items: center;
    gap: var(--at-s3);
    width: 100%;
    min-height: var(--at-hit);
    padding: var(--at-s2) var(--at-s3);
    /* Concentric with the menu: outer radius minus the menu's own padding. */
    border: 0;
    border-radius: calc(var(--at-r-lg) - var(--at-s2));
    background: transparent;
    color: var(--at-ink);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-medium);
    text-align: start;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--at-t-fast) var(--at-ease-out),
                color var(--at-t-fast) var(--at-ease-out);
}

.v-menu__item:hover,
.v-menu__item:focus-visible {
    background-color: var(--at-surface-hover);
    color: var(--at-ink);
    outline: none;
}

.v-menu__item:active { background-color: var(--at-surface-sunken); }

.v-menu__item .v-icon,
.v-menu__item .fi { color: var(--at-ink-secondary); font-size: var(--at-icon-sm); }

.v-menu__item--danger,
.v-menu__item--danger .v-icon,
.v-menu__item--danger .fi { color: var(--at-danger); }

.v-menu__item--danger:hover {
    background-color: var(--at-danger-soft);
    color: var(--at-danger);
}

.v-menu__sep {
    height: 1px;
    margin: var(--at-s2) var(--at-s3);
    background: var(--at-hairline);
}

.v-menu__label {
    padding: var(--at-s2) var(--at-s3) var(--at-s1);
    font-size: var(--at-text-xs);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-caps);
    text-transform: uppercase;
    color: var(--at-ink-faint);
}

/* Items come into the light in reading order. */
.v-menu.is-open .v-menu__item { animation: v-rise var(--at-t-base) var(--at-ease-out) backwards; }
.v-menu.is-open .v-menu__item:nth-child(2) { animation-delay: 20ms; }
.v-menu.is-open .v-menu__item:nth-child(3) { animation-delay: 40ms; }
.v-menu.is-open .v-menu__item:nth-child(n+4) { animation-delay: 60ms; }

/* =============================================================================
   7 · MODAL, SHEET & DIALOG
   -----------------------------------------------------------------------------
   One layer of temporary UI at a time. On touch the sheet is the default;
   the centred dialog is for a focused decision. The backdrop is a scrim,
   not glass — blur is a material, not a personality.
   ========================================================================== */
.v-backdrop {
    position: fixed;
    inset: 0;
    z-index: calc(var(--at-z-modal) - 1);
    background: var(--at-scrim);
    opacity: 0;
    transition: opacity var(--at-t-base) var(--at-ease-in);
}

.v-backdrop.is-open { opacity: 1; transition-timing-function: var(--at-ease-out); }

.v-modal {
    position: fixed;
    inset: 0;
    z-index: var(--at-z-modal);
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--at-s4);
}

.v-modal.is-open { display: flex; }

.v-modal__dialog {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 26rem;
    max-height: calc(100dvh - var(--at-s8));
    border-radius: var(--at-r-lg);
    background: var(--at-surface-raised);
    box-shadow: var(--at-edge), var(--at-shadow-lg);
    overflow: hidden;
    /* Arrives by coming into the light, where it stands. */
    opacity: 0;
    transition: opacity var(--at-t-slow) var(--at-ease-in);
}

.v-modal.is-open .v-modal__dialog {
    opacity: 1;
    transition: opacity var(--at-t-slower) var(--at-ease-out);
}

.v-modal__dialog--wide { max-width: 40rem; }

.v-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--at-s3);
    padding: var(--at-s4) var(--at-s5);
    border-bottom: 1px solid var(--at-hairline);
}

.v-modal__title {
    margin: 0;
    font-size: var(--at-text-lg);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-title);
}

.v-modal__body {
    padding: var(--at-s5);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.v-modal__footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--at-s2);
    padding: var(--at-s4) var(--at-s5);
    border-top: 1px solid var(--at-hairline);
}

/* --- Sheet: the bottom-edge surface for the Enfilade ----------------------- */
.v-sheet {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: var(--at-z-sheet);
    display: none;
    flex-direction: column;
    max-height: 86dvh;
    border-radius: var(--at-r-xl) var(--at-r-xl) 0 0;
    background: var(--at-surface-raised);
    box-shadow: var(--at-edge), var(--at-shadow-lg);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    /* A sheet is a door the hand moves: it travels, and physics apply. */
    transform: translateY(100%);
    transition: transform var(--at-t-slow) var(--at-ease-in);
}

.v-sheet.is-open {
    display: flex;
    transform: none;
    transition: transform var(--at-t-slower) var(--at-ease-out);
}

.v-sheet__grip {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 0.25rem;
    margin: var(--at-s3) auto var(--at-s1);
    border-radius: var(--at-r-pill);
    background: var(--at-hairline-strong);
}

.v-sheet__body {
    padding: var(--at-s2) var(--at-s2) var(--at-s4);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.v-sheet.is-open .v-menu__item { animation: v-rise var(--at-t-slow) var(--at-ease-out) backwards; }
.v-sheet.is-open .v-menu__item:nth-child(2) { animation-delay: 30ms; }
.v-sheet.is-open .v-menu__item:nth-child(3) { animation-delay: 60ms; }
.v-sheet.is-open .v-menu__item:nth-child(4) { animation-delay: 90ms; }
.v-sheet.is-open .v-menu__item:nth-child(n+5) { animation-delay: 120ms; }

/* From the Adjoining posture up, a sheet is simply a dialog. */
@media (min-width: 48em) {
    .v-sheet {
        inset: 0;
        top: 50%;
        bottom: auto;
        margin: auto;
        width: min(26rem, calc(100vw - var(--at-s8)));
        height: fit-content;
        max-height: 80dvh;
        border-radius: var(--at-r-lg);
        transform: translateY(-50%);
        opacity: 0;
        transition: opacity var(--at-t-slow) var(--at-ease-in);
    }

    .v-sheet.is-open {
        transform: translateY(-50%);
        opacity: 1;
        transition: opacity var(--at-t-slower) var(--at-ease-out);
    }

    .v-sheet__grip { display: none; }
}

/* =============================================================================
   8 · TABS & SEGMENTS
   ========================================================================== */
.v-tabs {
    display: flex;
    gap: var(--at-s1);
    border-bottom: 1px solid var(--at-hairline);
    overflow-x: auto;
    scrollbar-width: none;
}

.v-tabs::-webkit-scrollbar { display: none; }

.v-tab {
    position: relative;
    min-height: var(--at-hit);
    padding: var(--at-s3) var(--at-s4);
    border: 0;
    background: transparent;
    color: var(--at-ink-muted);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-semibold);
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--at-t-base) var(--at-ease-out);
}

.v-tab:hover { color: var(--at-ink); }

.v-tab[aria-selected="true"],
.v-tab.is-active { color: var(--at-ink); }

/* The current tab is underscored, not filled — weight and a rule, never
   colour alone. */
.v-tab[aria-selected="true"]::after,
.v-tab.is-active::after {
    content: "";
    position: absolute;
    inset-inline: var(--at-s3);
    bottom: -1px;
    height: 2px;
    border-radius: var(--at-r-pill);
    background-color: var(--at-accent);
}

/* --- Segmented control ----------------------------------------------------- */
.v-segment {
    display: inline-flex;
    gap: var(--at-s0);
    padding: var(--at-s0);
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface-sunken);
}

.v-segment__item {
    min-height: var(--at-control-h-sm);
    padding: 0 var(--at-s4);
    border: 0;
    border-radius: var(--at-r-pill);
    background: transparent;
    color: var(--at-ink-muted);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-medium);
    cursor: pointer;
    transition: background-color var(--at-t-base) var(--at-ease-out),
                color var(--at-t-base) var(--at-ease-out);
}

.v-segment__item:hover { color: var(--at-ink); }

/* A filter is not the primary act on a screen: its selected state is
   neutral plaster, never the accent. */
.v-segment__item[aria-selected="true"],
.v-segment__item.is-active {
    background-color: var(--at-surface-raised);
    color: var(--at-ink);
    font-weight: var(--at-weight-semibold);
    box-shadow: var(--at-shadow-xs);
}

/* =============================================================================
   9 · BADGES, SEALS, COUNTS
   -----------------------------------------------------------------------------
   Status is typographic. The seal is the fine mark that follows a name.
   ========================================================================== */
.v-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--at-s1);
    padding: 0.15rem 0.5rem;
    border-radius: var(--at-r-xs);
    background-color: var(--at-surface-sunken);
    color: var(--at-ink-secondary);
    font-size: var(--at-text-xs);
    font-weight: var(--at-weight-medium);
    line-height: 1.5;
    white-space: nowrap;
}

.v-badge--success { background: var(--at-success-soft); color: var(--at-success); }
.v-badge--danger  { background: var(--at-danger-soft);  color: var(--at-danger); }
.v-badge--warning { background: var(--at-warning-soft); color: var(--at-warning); }
.v-badge--info    { background: var(--at-info-soft);    color: var(--at-info); }
.v-badge--gilt    { background: var(--at-gilt-soft);    color: var(--at-gilt-ink); }

.v-seal {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1em;
    height: 1em;
    font-size: 0.82em;
    vertical-align: baseline;
    color: var(--at-ink-muted);
}

.v-seal--verified { color: var(--at-accent); }
.v-seal--staff    { color: var(--at-ink-secondary); }
.v-seal--gilt     { color: var(--at-gilt-ink); }
.v-seal--flag     { color: var(--at-danger); }

.v-dot {
    display: inline-block;
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--at-accent);
}

.v-dot--presence { background: var(--at-presence); }

.v-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.125rem;
    height: 1.125rem;
    padding: 0 0.3rem;
    border-radius: var(--at-r-pill);
    background-color: var(--at-accent);
    color: var(--at-accent-contrast);
    font-size: 0.6875rem;
    font-weight: var(--at-weight-bold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* =============================================================================
   10 · TAGS & CHIPS
   -----------------------------------------------------------------------------
   A tag is passive metadata; a chip is an interactive filter.
   ========================================================================== */
.v-tag {
    display: inline-flex;
    align-items: center;
    gap: var(--at-s1);
    padding: 0.1rem 0.5rem;
    border-radius: var(--at-r-xs);
    background: var(--at-surface-sunken);
    color: var(--at-ink-secondary);
    font-size: var(--at-text-xs);
    font-weight: var(--at-weight-medium);
    white-space: nowrap;
}

.v-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--at-s2);
    min-height: var(--at-control-h-sm);
    padding: 0 var(--at-s4);
    border: 0;
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface);
    box-shadow: var(--at-edge), var(--at-shadow-xs);
    color: var(--at-ink-secondary);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-medium);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--at-t-fast) var(--at-ease-out),
                color var(--at-t-fast) var(--at-ease-out),
                box-shadow var(--at-t-fast) var(--at-ease-out),
                translate var(--at-t-instant) var(--at-ease-out);
}

.v-chip:hover { background-color: var(--at-surface-hover); color: var(--at-ink); }
.v-chip:active { translate: 0 1px; box-shadow: none; }

.v-chip[aria-pressed="true"],
.v-chip.is-active {
    background-color: var(--at-surface-raised);
    color: var(--at-ink);
    font-weight: var(--at-weight-semibold);
    box-shadow: var(--at-edge), var(--at-shadow-sm);
}

/* =============================================================================
   11 · PROGRESS
   ========================================================================== */
.v-progress {
    width: 100%;
    height: 0.375rem;
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface-sunken);
    overflow: hidden;
}

.v-progress__fill {
    height: 100%;
    border-radius: inherit;
    background-color: var(--at-accent);
    transition: width var(--at-t-slower) var(--at-ease-inout);
}

.v-progress--gilt .v-progress__fill { background-color: var(--at-gilt); }

.v-progress--indeterminate .v-progress__fill {
    width: 40%;
    animation: v-progress-sweep 1.2s var(--at-ease-inout) infinite;
}

@keyframes v-progress-sweep {
    from { transform: translateX(-100%); }
    to   { transform: translateX(350%); }
}

/* =============================================================================
   12 · TOOLTIP
   -----------------------------------------------------------------------------
   CSS-only: <button data-v-tooltip="Label">. Pointer surfaces only — on a
   touch device a long press already means something else.
   ========================================================================== */
[data-v-tooltip] { position: relative; }

@media (hover: hover) {
    [data-v-tooltip]::after {
        content: attr(data-v-tooltip);
        position: absolute;
        bottom: calc(100% + var(--at-s2));
        left: 50%;
        z-index: var(--at-z-tooltip);
        padding: var(--at-s1) var(--at-s3);
        border-radius: var(--at-r-sm);
        background: var(--at-ink);
        color: var(--at-ink-inverse);
        font-size: var(--at-text-xs);
        font-weight: var(--at-weight-medium);
        letter-spacing: var(--at-tracking-meta);
        white-space: nowrap;
        pointer-events: none;
        opacity: 0;
        transform: translateX(-50%);
        transition: opacity var(--at-t-fast) var(--at-ease-out);
        transition-delay: 0ms;
    }

    /* A tooltip waits to be asked; it never pounces. */
    [data-v-tooltip]:hover::after,
    [data-v-tooltip]:focus-visible::after {
        opacity: 1;
        transition-delay: 400ms;
    }
}

/* =============================================================================
   13 · AVATAR
   -----------------------------------------------------------------------------
   The only true circles in the product (law 5), which is what makes people
   the most distinct shape on any screen.
   ========================================================================== */
.v-avatar {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface-sunken);
    color: var(--at-ink-muted);
    overflow: hidden;
}

.v-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}

.v-avatar--xs  { width: 1.5rem;  height: 1.5rem; }
.v-avatar--sm  { width: 2rem;    height: 2rem; }
.v-avatar--lg  { width: 3.5rem;  height: 3.5rem; }
.v-avatar--xl  { width: 6rem;    height: 6rem; }
.v-avatar--2xl { width: 8.25rem; height: 8.25rem; }

/* A separating ring keeps a pale photograph from bleeding into the surface
   behind it — true in both materials, so it is unconditional. */
.v-avatar--ring { box-shadow: 0 0 0 1px var(--at-hairline-strong); }

/* Seated: the avatar sits in a cut-out of the canvas (profile header). It also
   becomes its own stacking context: the loader gives the inner <img> a z-index
   for its skeleton reveal, and without isolation that z-index escapes the
   avatar and paints the photo OVER the sibling camera / info controls seated on
   its edge. Isolation keeps that internal order contained so the controls stay
   on top and clickable. */
.v-avatar--seated {
    box-shadow: 0 0 0 4px var(--at-bg), var(--at-shadow-md);
    isolation: isolate;
}

.v-avatar__presence {
    position: absolute;
    inset-inline-end: 0;
    inset-block-end: 0;
    width: 26%;
    height: 26%;
    min-width: 0.5rem;
    min-height: 0.5rem;
    border-radius: 50%;
    background: var(--at-presence);
    box-shadow: 0 0 0 2px var(--at-surface);
}

.v-avatar-stack { display: inline-flex; align-items: center; }

.v-avatar-stack .v-avatar + .v-avatar {
    margin-inline-start: -0.625rem;
    box-shadow: 0 0 0 2px var(--at-surface);
}

/* =============================================================================
   14 · LISTS & ROWS
   -----------------------------------------------------------------------------
   The grouped row list (settings) and the person row (suggestions, members,
   followers, search results). Rows are data; markup only renders them.
   ========================================================================== */
.v-group {
    border-radius: var(--at-r-lg);
    background-color: var(--at-surface);
    box-shadow: var(--at-edge), var(--at-shadow-sm);
    overflow: hidden;
}

.v-group + .v-group { margin-top: var(--at-s5); }

.v-group__heading {
    margin: 0 0 var(--at-s2) var(--at-s1);
    font-size: var(--at-text-xs);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-caps);
    text-transform: uppercase;
    color: var(--at-ink-faint);
}

.v-rowitem {
    display: flex;
    align-items: center;
    gap: var(--at-s3);
    width: 100%;
    min-height: var(--at-hit);
    padding: var(--at-s3) var(--at-s4);
    border: 0;
    background: transparent;
    color: var(--at-ink);
    font-size: var(--at-text-md);
    font-weight: var(--at-weight-medium);
    text-align: start;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--at-t-fast) var(--at-ease-out);
}

/* Rows touch, so they get a joint. */
.v-rowitem + .v-rowitem { border-top: 1px solid var(--at-hairline); }

.v-rowitem:hover  { background-color: var(--at-surface-hover); color: var(--at-ink); }
.v-rowitem:active { background-color: var(--at-surface-sunken); }

.v-rowitem:focus-visible {
    outline: 2px solid var(--at-accent);
    outline-offset: -2px;
}

/* Monochrome ink in a quiet well — status is typographic, never a grid of
   coloured tiles. */
.v-rowitem__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.125rem;
    height: 2.125rem;
    border-radius: calc(var(--at-r-md) - var(--at-s1));
    background: var(--at-surface-sunken);
    color: var(--at-ink-secondary);
    font-size: var(--at-icon-sm);
}

.v-rowitem__label { flex: 1 1 auto; min-width: 0; }

.v-rowitem__meta {
    flex: 0 0 auto;
    color: var(--at-ink-muted);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-regular);
    font-variant-numeric: tabular-nums;
}

.v-rowitem__chevron {
    flex: 0 0 auto;
    color: var(--at-ink-faint);
    font-size: var(--at-icon-xs);
    transition: transform var(--at-t-base) var(--at-ease-out),
                color var(--at-t-base) var(--at-ease-out);
}

.v-rowitem:hover .v-rowitem__chevron {
    transform: translateX(2px);
    color: var(--at-ink-secondary);
}

[dir="rtl"] .v-rowitem:hover .v-rowitem__chevron { transform: translateX(-2px); }

/* A chosen option states itself in weight and a check; the chevron leaves. */
.v-rowitem[aria-current="true"] .v-rowitem__label { font-weight: var(--at-weight-semibold); }
.v-rowitem__check { flex: 0 0 auto; color: var(--at-accent-ink); }

/* --- Person row ------------------------------------------------------------
   One definition for feed suggestions, follower lists, like lists and
   search results. */
.v-person {
    display: flex;
    align-items: center;
    gap: var(--at-s3);
    min-height: var(--at-hit);
    padding: var(--at-s2);
    border-radius: var(--at-r-md);
    transition: background-color var(--at-t-fast) var(--at-ease-out);
}

.v-person__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    color: inherit;
}

.v-person__name {
    display: flex;
    align-items: center;
    gap: var(--at-s1);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-semibold);
    color: var(--at-ink);
    line-height: 1.35;
}

.v-person__sub {
    font-size: var(--at-text-xs);
    letter-spacing: var(--at-tracking-meta);
    color: var(--at-ink-muted);
    line-height: 1.35;
}

/* Interactive person rows (search results, chat list) light up as a whole. */
.v-person--action { cursor: pointer; }
.v-person--action:hover { background-color: var(--at-surface-hover); }
.v-person--action:active { background-color: var(--at-surface-sunken); }
.v-person--action:hover .v-person__name { text-decoration: none; text-underline-offset: 2px; }

/* =============================================================================
   15 · TABLE & SWATCHES
   -----------------------------------------------------------------------------
   Working density: hairline rows, tabular numerals, no zebra. Luminance on
   hover is enough to track a row across a wide table.
   ========================================================================== */
.v-table-wrap {
    overflow-x: auto;
    border-radius: var(--at-r-lg);
    background: var(--at-surface);
    box-shadow: var(--at-edge), var(--at-shadow-sm);
}

.v-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--at-text-sm);
}

.v-table th {
    position: sticky;
    top: 0;
    padding: var(--at-s3) var(--at-s4);
    background: var(--at-surface-raised);
    color: var(--at-ink-faint);
    font-size: var(--at-text-xs);
    font-weight: var(--at-weight-semibold);
    letter-spacing: var(--at-tracking-caps);
    text-transform: uppercase;
    text-align: start;
    white-space: nowrap;
    border-bottom: 1px solid var(--at-hairline);
}

.v-table td {
    padding: var(--at-s3) var(--at-s4);
    border-bottom: 1px solid var(--at-hairline);
    color: var(--at-ink);
    vertical-align: middle;
    font-variant-numeric: tabular-nums;
}

.v-table tbody tr { transition: background-color var(--at-t-fast) var(--at-ease-out); }
.v-table tbody tr:hover { background-color: var(--at-surface-hover); }
.v-table tbody tr:last-child td { border-bottom: 0; }

.v-table td.is-num { text-align: end; }

/* --- Swatch grid (chat themes and any future palette picker) --------------- */
.v-swatches {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));
    gap: var(--at-s4) var(--at-s2);
}

.v-swatch {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--at-s2);
    color: var(--at-ink-muted);
    font-size: var(--at-text-xs);
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}

.v-swatch:hover { color: var(--at-ink); }

.v-swatch__chip {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.625rem;
    height: 3.625rem;
    border-radius: var(--at-r-pill);
    box-shadow: var(--at-shadow-xs);
    transition: box-shadow var(--at-t-base) var(--at-ease-out),
                translate var(--at-t-base) var(--at-ease-out);
}

.v-swatch:hover .v-swatch__chip  { translate: 0 -2px; box-shadow: var(--at-shadow-md); }
.v-swatch:active .v-swatch__chip { translate: 0 1px; box-shadow: var(--at-shadow-xs); }

.v-swatch.is-selected .v-swatch__chip {
    box-shadow: 0 0 0 2px var(--at-surface), 0 0 0 4px var(--at-accent);
}

.v-swatch.is-selected .v-swatch__label {
    color: var(--at-accent-ink);
    font-weight: var(--at-weight-semibold);
}

.v-swatch__chip img { pointer-events: none; }

/* =============================================================================
   16 · ALERT · TOAST · SKELETON · EMPTY STATE · SHARED MOTION
   ========================================================================== */
/* An alert is a note in the margin: a wash of its pigment behind ink, with
   the meaning carried by the words beside it. */
.v-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--at-s3);
    padding: var(--at-s3) var(--at-s4);
    border-radius: var(--at-r-md);
    background-color: var(--at-surface-raised);
    color: var(--at-ink);
    font-size: var(--at-text-sm);
    line-height: var(--at-leading-normal);
}

.v-alert--success { background: var(--at-success-soft); color: var(--at-success); }
.v-alert--danger  { background: var(--at-danger-soft);  color: var(--at-danger); }
.v-alert--warning { background: var(--at-warning-soft); color: var(--at-warning); }
.v-alert--info    { background: var(--at-info-soft);    color: var(--at-info); }

/* The toast states one fact and leaves. Ink-on-inverse so it belongs to the
   system rather than to any one page. */
.v-toast {
    position: fixed;
    left: 50%;
    bottom: calc(var(--at-tabbar-h) + var(--at-s4) + env(safe-area-inset-bottom, 0px));
    z-index: var(--at-z-toast);
    min-width: 13rem;
    max-width: min(26rem, calc(100vw - var(--at-s7)));
    padding: var(--at-s3) var(--at-s5);
    border-radius: var(--at-r-md);
    background-color: var(--at-ink);
    color: var(--at-ink-inverse);
    box-shadow: var(--at-shadow-lg);
    font-size: var(--at-text-sm);
    font-weight: var(--at-weight-medium);
    text-align: center;
    opacity: 0;
    transform: translateX(-50%) translateY(8px);
    pointer-events: none;
    transition: opacity var(--at-t-base) var(--at-ease-out),
                transform var(--at-t-base) var(--at-ease-out);
}

.v-toast.is-visible { opacity: 1; transform: translateX(-50%) translateY(0); }

@media (min-width: 48em) { .v-toast { bottom: var(--at-s6); } }

/* --- Skeleton: light sweeping across unlit plaster ------------------------- */
.v-skeleton {
    background-color: var(--at-surface-sunken);
    background-image: var(--at-skeleton);
    background-size: 200% 100%;
    border-radius: var(--at-r-sm);
    animation: v-shimmer 1.6s var(--at-ease-inout) infinite;
}

.v-skeleton--text   { height: 0.75rem; margin-bottom: var(--at-s2); }
.v-skeleton--title  { height: 1.125rem; width: 45%; margin-bottom: var(--at-s3); }
.v-skeleton--circle { border-radius: var(--at-r-pill); }
.v-skeleton--avatar { flex: 0 0 auto; width: 2.5rem; height: 2.5rem; border-radius: var(--at-r-pill); }
.v-skeleton--media  { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--at-r-xl); }
.v-skeleton--block  { width: 100%; height: 100%; }

.v-skeleton--text:last-child { width: 70%; }

/* The feed's shape before the feed exists, so nothing jumps on arrival.
   Mark these aria-hidden and the region aria-busy. */
.v-skeleton-post {
    padding: var(--at-s4);
    border-radius: var(--at-r-lg);
    background-color: var(--at-surface);
    box-shadow: var(--at-edge), var(--at-shadow-sm);
}

.v-skeleton-post__head {
    display: flex;
    align-items: center;
    gap: var(--at-s3);
    margin-bottom: var(--at-s4);
}

.v-skeleton-post__head .v-skeleton--text { flex: 1 1 auto; max-width: 10rem; margin: 0; }

@keyframes v-shimmer {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .v-skeleton { background-image: none; }
}

/* --- Empty state: an invitation, not an apology ---------------------------- */
.v-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--at-s2);
    padding: var(--at-s10) var(--at-s6);
    text-align: center;
}

/* The mark sits in a recess: an empty room is a space, not an object. */
.v-empty__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.75rem;
    height: 3.75rem;
    margin-bottom: var(--at-s3);
    border-radius: var(--at-r-pill);
    background-color: var(--at-surface-sunken);
    color: var(--at-ink-faint);
    font-size: var(--at-icon-lg);
}

.v-empty__title {
    margin: 0;
    font-family: var(--at-font-inscription);
    font-size: var(--at-text-xl);
    font-weight: var(--at-weight-display);
    letter-spacing: var(--at-tracking-display);
    color: var(--at-ink);
}

.v-empty__text {
    margin: 0;
    max-width: 38ch;
    font-size: var(--at-text-sm);
    line-height: var(--at-leading-relaxed);
    color: var(--at-ink-muted);
}

.v-empty__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--at-s2);
    margin-top: var(--at-s5);
}

/* --- Shared motion ---------------------------------------------------------
   Things arrive by coming into the light. v-rise is the name every product
   and polish rule references; its content is luminance, not travel. */
@keyframes v-rise {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes v-pop {
    from { transform: scale(0.94); }
    to   { transform: scale(1); }
}

/* The two rationed moments of joy. 1 — a like blooms. */
@keyframes v-bloom {
    0%   { transform: scale(0.4);  opacity: 0; }
    30%  { transform: scale(1.25); opacity: 1; }
    60%  { transform: scale(1); }
    100% { transform: scale(1);    opacity: 1; }
}

.v-bloom { animation: v-bloom 420ms var(--at-ease-spring); }

/* 2 — value glints once, like light crossing metal. */
@keyframes v-glint {
    0%   { transform: translateX(-150%) skewX(-18deg); opacity: 0; }
    35%  { opacity: 0.45; }
    100% { transform: translateX(250%) skewX(-18deg);  opacity: 0; }
}

.v-glint { position: relative; overflow: hidden; }

.v-glint::after {
    content: "";
    position: absolute;
    inset-block: 0;
    width: 40%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.32), transparent);
    animation: v-glint 900ms var(--at-ease-inout) 1;
    pointer-events: none;
}
