/* ---- the page kit -----------------------------------------------------------------------------------------------------
   The Panel's and the project page's design language, pulled out so every other page can speak it: a hero banner to
   open the page (PageHero), cards with a tone hairline and a tinted icon (SectionCard), dashed empty states that offer
   the first step (EmptyState), and the lists, tiles, tables, chips and switches the two pages draw by hand. Colours
   come from the theme tokens and the chart palette only, so light and dark both follow; the hero is dark in both,
   like the project hero, because it sits on art.

   Loaded after app.css and before the page sheets, so a page can still nudge any of it. */

/* The kit's boxes size by their border, as Bootstrap sets for the app, so a tile's padding never pushes it out of its cell. */
.hero, .hero *, .ui-card, .ui-tile, .ui-empty, .ui-stat, .ui-row, .ui-search input { box-sizing: border-box; }

/* ---- tones: one variable a card, chip, tile or empty state reads its colour from ------------------------------------ */

.ui-tone--1 { --tone: var(--rl-chart-1); }
.ui-tone--2 { --tone: var(--rl-chart-2); }
.ui-tone--3 { --tone: var(--rl-chart-3); }
.ui-tone--4 { --tone: var(--rl-chart-4); }
.ui-tone--5 { --tone: var(--rl-chart-5); }
.ui-tone--accent { --tone: var(--rl-accent); }
.ui-tone--ok { --tone: var(--rl-ok); }
.ui-tone--warn { --tone: var(--rl-warning, #e3b341); }
.ui-tone--danger, .ui-tone--bad { --tone: var(--rl-danger); }
.ui-tone--muted { --tone: var(--rl-text-muted); }

/* ---- the hero ---------------------------------------------------------------------------------------------------------- */

.hero {
    --hero-hue: 225;
    position: relative;
    isolation: isolate;
    container: hero / inline-size;
    display: flex;
    flex-direction: column;
    margin: 0 0 1rem;
    border-radius: 18px;
    color: #fff;
    border: 1px solid color-mix(in srgb, var(--rl-border) 60%, transparent);
    box-shadow: var(--rl-shadow-md);
    animation: rl-rise 0.24s var(--rl-ease) both;
}

/* Not clipped itself, so a menu in its buttons can hang below it; lifted while one is open. */
.hero:focus-within, .hero:has(details[open]) { z-index: 4; }

.hero__art {
    position: absolute;
    inset: 0;
    z-index: -1;
    overflow: hidden;
    border-radius: inherit;
    background:
        radial-gradient(50% 120% at 86% 10%, hsl(var(--hero-hue) 85% 62% / 0.5), transparent 62%),
        radial-gradient(40% 110% at 8% 120%, hsl(calc(var(--hero-hue) + 55) 80% 58% / 0.42), transparent 66%),
        radial-gradient(30% 80% at 46% -20%, hsl(calc(var(--hero-hue) - 40) 80% 60% / 0.3), transparent 70%),
        linear-gradient(120deg, hsl(var(--hero-hue) 48% 15%), hsl(calc(var(--hero-hue) + 35) 55% 8%));
}

/* A dot grid that fades in from the left, as on the project hero. */
.hero__art::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: radial-gradient(rgb(255 255 255 / 0.15) 1px, transparent 1.4px);
    background-size: 22px 22px;
    mask-image: linear-gradient(90deg, transparent 0%, #000 50%, #000 100%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 50%, #000 100%);
}

/* The brand's eclipse, quietly, on the right. */
.hero__orb {
    position: absolute;
    top: 50%;
    right: 7%;
    width: clamp(6rem, 15cqi, 10.5rem);
    aspect-ratio: 1;
    border-radius: 50%;
    transform: translateY(-50%);
    background: radial-gradient(circle at 38% 36%, hsl(var(--hero-hue) 40% 13%), hsl(var(--hero-hue) 45% 5%) 70%);
    box-shadow:
        0 0 0 1.5px hsl(var(--hero-hue) 95% 82% / 0.7),
        0 0 24px 5px hsl(var(--hero-hue) 95% 70% / 0.4),
        0 0 80px 20px hsl(calc(var(--hero-hue) + 40) 90% 60% / 0.26);
    animation: hero-glow 7s ease-in-out infinite alternate;
}

@keyframes hero-glow {
    to {
        box-shadow:
            0 0 0 1.5px hsl(var(--hero-hue) 95% 86% / 0.85),
            0 0 32px 8px hsl(var(--hero-hue) 95% 72% / 0.52),
            0 0 104px 28px hsl(calc(var(--hero-hue) + 40) 90% 62% / 0.34);
    }
}

.hero__body {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    padding: 1.35rem 1.4rem 1.25rem;
}

.hero__icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 3.4rem;
    aspect-ratio: 1;
    border: 2px solid rgb(255 255 255 / 0.85);
    border-radius: 24%;
    background: linear-gradient(140deg, hsl(var(--hero-hue) 70% 55%), hsl(calc(var(--hero-hue) + 50) 70% 42%));
    box-shadow: 0 8px 24px rgb(0 0 0 / 0.4);
    color: #fff;
}

.hero__icon svg { width: 1.6rem; height: 1.6rem; }
.hero__icon img { width: 74%; height: 74%; object-fit: contain; }
.hero__icon--mark { background: rgb(10 12 18 / 0.55); }

.hero__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.2rem; }

.hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    align-self: flex-start;
    margin: 0;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgb(255 255 255 / 0.68);
    text-decoration: none;
}

a.hero__crumb { border-radius: 6px; transition: color var(--rl-dur) var(--rl-ease); }
a.hero__crumb:hover { color: #fff; }
a.hero__crumb:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.hero__crumb svg { width: 0.8rem; height: 0.8rem; transform: rotate(180deg); }

.hero__titleRow { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.65rem; min-width: 0; }

.hero__title {
    margin: 0;
    min-width: 0;
    font-size: clamp(1.4rem, 3.2cqi, 1.85rem);
    font-weight: 750;
    line-height: 1.15;
    letter-spacing: -0.015em;
    overflow-wrap: anywhere;
    color: #fff;
    text-shadow: 0 2px 14px rgb(0 0 0 / 0.45);
}

.hero__lede {
    margin: 0.15rem 0 0;
    max-width: 48rem;
    font-size: 0.92rem;
    line-height: 1.5;
    color: rgb(255 255 255 / 0.84);
    text-shadow: 0 1px 8px rgb(0 0 0 / 0.45);
}

.hero__lede strong, .hero__lede em { color: #fff; font-style: normal; font-weight: 600; }
.hero__lede a, .hero__lede a:visited { color: #fff; text-decoration: underline; text-decoration-color: rgb(255 255 255 / 0.5); text-underline-offset: 2px; }
.hero__lede a:hover { text-decoration-color: #fff; }
.hero__lede code { color: #fff; background: rgb(255 255 255 / 0.14); }

.hero__chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0.35rem 0 0; padding: 0; }

/* A pill on the banner: in the chips row, or beside the title as its badge. */
.hero__chip, .hero .pill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin: 0;
    padding: 0.12rem 0.55rem;
    border-radius: 999px;
    background: rgb(255 255 255 / 0.14);
    border: 1px solid rgb(255 255 255 / 0.16);
    font-size: 0.76rem;
    font-weight: 500;
    color: rgb(255 255 255 / 0.92);
    white-space: nowrap;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.hero__chip--accent, .hero .pill--online { background: color-mix(in srgb, var(--rl-accent) 55%, transparent); border-color: color-mix(in srgb, var(--rl-accent) 80%, #fff 10%); font-weight: 600; }
.hero__chip--ok { background: color-mix(in srgb, var(--rl-ok) 45%, transparent); border-color: color-mix(in srgb, var(--rl-ok) 70%, #fff 10%); }
.hero__chip--warn, .hero .pill--warn { background: rgb(227 179 65 / 0.5); border-color: rgb(227 179 65 / 0.8); color: #fff; }
.hero__chip--bad, .hero .pill--offline { background: color-mix(in srgb, var(--rl-danger) 45%, transparent); border-color: color-mix(in srgb, var(--rl-danger) 70%, #fff 10%); }
.hero__chip svg { width: 0.8rem; height: 0.8rem; }

/* The page's buttons, on glass. A primary keeps its colour and becomes the pill the project hero uses. */
.hero__actions {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 0.5rem;
    max-width: 60%;
}

.hero__actions .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    border-radius: 999px;
    padding: 0.45rem 0.95rem;
    white-space: nowrap;
}

.hero__actions .btn svg { width: 1rem; height: 1rem; flex: none; }

.hero__actions .btn:not(.btn--primary, .btn--destructive) {
    background: rgb(10 12 18 / 0.38);
    border: 1px solid rgb(255 255 255 / 0.22);
    color: #fff;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: none;
}

.hero__actions .btn:not(.btn--primary, .btn--destructive):hover { background: rgb(10 12 18 / 0.6); border-color: rgb(255 255 255 / 0.38); }
.hero__actions .btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.hero__actions .btn--primary { box-shadow: 0 6px 20px rgb(0 0 0 / 0.35); }
.hero__actions .btn--danger:not(.btn--primary) { color: #ffb4ae; }

.hero__actions select, .hero__actions input:not([type=checkbox], [type=radio]) {
    min-height: 0;
    padding: 0.4rem 0.75rem;
    border: 1px solid rgb(255 255 255 / 0.22);
    border-radius: 999px;
    background-color: rgb(10 12 18 / 0.38);
    color: #fff;
    font: inherit;
    font-size: 0.88rem;
}

.hero__actions select option { color: var(--rl-text); background: var(--rl-surface); }
.hero__actions label { color: rgb(255 255 255 / 0.85); font-size: 0.85rem; }

/* A segmented switch on the banner. */
.hero .ui-seg { background: rgb(10 12 18 / 0.38); border-color: rgb(255 255 255 / 0.2); }
.hero .ui-seg button { color: rgb(255 255 255 / 0.72); }
.hero .ui-seg button:hover { color: #fff; }
.hero .ui-seg button.is-on { background: rgb(255 255 255 / 0.9); color: #10131a; }

/* The figures along the foot. */
.hero__stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 2rem;
    margin: 0;
    padding: 0.55rem 1.4rem 0.65rem;
    border-radius: 0 0 17px 17px;
    background: rgb(6 8 12 / 0.42);
    border-top: 1px solid rgb(255 255 255 / 0.1);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

/* A Stats or Chips fragment that drew nothing (still loading, an empty list) leaves no band behind. */
.hero__stats:not(:has(*)), .hero__chips:not(:has(*)) { display: none; }

.hero__stat { display: flex; flex-direction: column-reverse; min-width: 0; }
.hero__stat dt { font-size: 0.66rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: rgb(255 255 255 / 0.62); white-space: nowrap; }
.hero__stat dd { display: flex; align-items: baseline; gap: 0.3rem; margin: 0; font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hero__stat dd small { font-size: 0.72rem; font-weight: 500; color: rgb(255 255 255 / 0.6); }
.hero__stat dd a { color: #fff; text-decoration: none; border-bottom: 1px dashed rgb(255 255 255 / 0.5); }
.hero__stat dd a:hover { border-bottom-style: solid; }
.hero__stat--ok dd { color: #7ee2a8; }
.hero__stat--warn dd { color: #f5cf6b; }
.hero__stat--bad dd { color: #ff9e96; }

/* A tool page's banner: the form below wants the room. */
.hero--compact .hero__body { padding: 0.9rem 1.15rem 0.85rem; gap: 0.85rem; }
.hero--compact .hero__icon { width: 2.6rem; border-width: 1.5px; }
.hero--compact .hero__icon svg { width: 1.25rem; height: 1.25rem; }
.hero--compact .hero__title { font-size: clamp(1.2rem, 2.6cqi, 1.45rem); }
.hero--compact .hero__lede { font-size: 0.85rem; }
.hero--compact .hero__orb { width: clamp(4.5rem, 10cqi, 7rem); right: 4%; }

@container hero (max-width: 44rem) {
    .hero__body { flex-wrap: wrap; align-items: flex-start; padding: 1.15rem 1rem 1rem; gap: 0.85rem; }
    .hero__text { flex-basis: calc(100% - 4.5rem); }
    .hero__actions { flex-basis: 100%; max-width: none; justify-content: flex-start; }
    .hero__stats { gap: 0.25rem 1.25rem; padding: 0.5rem 1rem; }
    .hero__orb { width: 7rem; right: -2.5rem; top: 34%; opacity: 0.7; }
    .hero--compact .hero__orb { width: 5rem; right: -1.5rem; }
}

/* ---- section cards ------------------------------------------------------------------------------------------------------ */

/* The colour is a hairline along the top and the tint of the icon, so a card is found by colour as well as by name. An
   inset shadow rather than a border, so it follows the rounded corners. */
.ui-card {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 1rem 1.1rem;
    box-shadow: inset 0 2px 0 color-mix(in srgb, var(--tone, var(--rl-accent)) 75%, transparent), var(--rl-shadow-sm);
}

.ui-card > * { margin-top: 0; margin-bottom: 0; }

.ui-card__head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem 0.75rem; }

.ui-card .ui-card__title, .ui-card__title {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    min-width: 0;
    margin: 0;
    font-size: 1rem;
    font-weight: 650;
}

.ui-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.ui-card__actions .btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem; }
.ui-card__actions .btn svg { width: 0.95rem; height: 0.95rem; }
.ui-card__actions > a:not(.btn) { color: var(--rl-text-muted); font-size: 0.8rem; text-decoration: underline; text-underline-offset: 2px; }
.ui-card__actions > a:not(.btn):hover { color: var(--rl-text); }

.ui-card__hint:empty, .ui-card__actions:not(:has(*)) { display: none; }
.ui-card > .ui-toolbar { margin: 0; }
.ui-card > .ui-search { flex: none; }

.ui-card__hint { margin: 0; max-width: 52rem; color: var(--rl-text-muted); font-size: 0.84rem; line-height: 1.5; }
.ui-card__hint strong { color: var(--rl-text); font-weight: 600; }

/* The tinted square an icon sits in: card titles, list rows, anything that wants the Panel's icon. */
.ui-ico {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 0.5rem;
    background: color-mix(in srgb, var(--tone, var(--rl-accent)) 16%, transparent);
    color: var(--tone, var(--rl-accent));
}

.ui-ico svg { width: 1rem; height: 1rem; }
.ui-ico--lg { width: 2.4rem; height: 2.4rem; border-radius: 10px; }
.ui-ico--lg svg { width: 1.2rem; height: 1.2rem; }

.ui-count {
    min-width: 1.4rem;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    background: var(--rl-surface-sunken);
    color: var(--rl-text-muted);
    font-size: 0.74rem;
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* The small uppercase heading inside a card. */
.ui-h3 {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0.35rem 0 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--rl-text-muted);
}

.ui-sub { margin: 0; color: var(--rl-text-muted); font-size: 0.84rem; line-height: 1.45; }

/* ---- empty states ------------------------------------------------------------------------------------------------------- */

.ui-empty {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin: 0;
    padding: 0.85rem 1rem;
    border: 1px dashed var(--rl-border);
    border-radius: 12px;
    color: var(--rl-text-muted);
    font-size: 0.88rem;
}

.ui-empty__ico {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.6rem;
    height: 2.6rem;
    border: 1px dashed color-mix(in srgb, var(--tone, var(--rl-accent)) 55%, var(--rl-border));
    border-radius: 12px;
    background: color-mix(in srgb, var(--tone, var(--rl-accent)) 9%, transparent);
    color: var(--tone, var(--rl-accent));
}

.ui-empty__ico svg { width: 1.15rem; height: 1.15rem; }
.ui-empty__text { flex: 1 1 14rem; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; line-height: 1.45; }
.ui-empty__text strong { color: var(--rl-text); font-size: 0.92rem; font-weight: 600; }
.ui-empty__actions:not(:has(*)) { display: none; }
.ui-empty__actions { flex: none; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.ui-empty__actions .btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.ui-empty__actions .btn svg { width: 0.95rem; height: 0.95rem; }

.ui-empty--big {
    flex-direction: column;
    justify-content: center;
    gap: 0.75rem;
    padding: 2.25rem 1.25rem;
    text-align: center;
    background: color-mix(in srgb, var(--tone, var(--rl-accent)) 3%, transparent);
}

.ui-empty--big .ui-empty__ico { width: 3.6rem; height: 3.6rem; border-radius: 16px; }
.ui-empty--big .ui-empty__ico svg { width: 1.6rem; height: 1.6rem; }
.ui-empty--big .ui-empty__text { flex: none; align-items: center; max-width: 34rem; }
.ui-empty--big .ui-empty__text strong { font-size: 1.05rem; }
.ui-empty--big .ui-empty__actions { justify-content: center; }

/* ---- layout ------------------------------------------------------------------------------------------------------------- */

/* A page body of cards, one after another. */
.ui-stack { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }

/* A main column beside a narrower side one, as on the project page; the side drops under the main when they no
   longer fit. Flex rather than a container query, so it works wherever it is put. */
.ui-split { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 1rem; }
.ui-split__main { flex: 999 1 34rem; min-width: 0; display: flex; flex-direction: column; gap: 1rem; }
.ui-split__side { flex: 1 1 19rem; min-width: 0; display: flex; flex-direction: column; gap: 1rem; }

/* Cards side by side while each still gets a readable width. */
.ui-pair { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); align-items: start; }

.ui-stack > .card, .ui-split__main > .card, .ui-split__side > .card, .ui-pair > .card, .ui-stats > .card { margin-bottom: 0; }

/* A page wrapped in the kit gets the hero's rhythm between its blocks. */
.admin > .ui-stack, .admin > .ui-split, .admin > .ui-pair, .admin > .ui-stats { margin-bottom: 1rem; }

/* ---- stat tiles: figures outside the hero ---------------------------------------------------------------------------- */

.ui-stats { display: grid; gap: 0.85rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }

.ui-stat {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.8rem 0.95rem;
    border: 1px solid var(--rl-border);
    border-radius: var(--rl-radius);
    background: var(--rl-surface);
    box-shadow: inset 0 2px 0 color-mix(in srgb, var(--tone, var(--rl-accent)) 75%, transparent), var(--rl-shadow-sm);
    min-width: 0;
}

.ui-stat__label { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--rl-text-muted); }
.ui-stat__value { font-size: 1.7rem; font-weight: 750; line-height: 1.1; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.ui-stat__note { font-size: 0.78rem; color: var(--rl-text-muted); }
.ui-stat__value.is-ok { color: var(--rl-ok); }
.ui-stat__value.is-bad { color: var(--rl-danger); }

/* ---- lists ---------------------------------------------------------------------------------------------------------------- */

.ui-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ui-list > li { min-width: 0; }
.ui-list > li + li { border-top: 1px solid var(--rl-border); }

.ui-row {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-width: 0;
    padding: 0.55rem 0.15rem;
    color: inherit;
    text-decoration: none;
}

a.ui-row, button.ui-row { width: 100%; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; border-radius: 10px; padding-inline: 0.5rem; transition: background var(--rl-dur) var(--rl-ease); }
a.ui-row:hover, button.ui-row:hover { background: var(--rl-surface-sunken); color: inherit; }
a.ui-row:focus-visible, button.ui-row:focus-visible { outline: 2px solid var(--rl-accent); outline-offset: 1px; }

.ui-row__lead { flex: none; }
.ui-row__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.ui-row__title { display: flex; align-items: center; gap: 0.4rem; min-width: 0; font-weight: 600; font-size: 0.9rem; }
.ui-row__title > :not(.ui-chip, .pill, svg) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-row__sub { color: var(--rl-text-muted); font-size: 0.8rem; line-height: 1.4; overflow: hidden; text-overflow: ellipsis; }
.ui-row__meta { flex: none; color: var(--rl-text-muted); font-size: 0.78rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
.ui-row__end { flex: none; display: flex; align-items: center; gap: 0.35rem; }
.ui-row__go { flex: none; width: 1rem; height: 1rem; color: var(--rl-text-muted); transition: transform var(--rl-dur) var(--rl-ease); }
a.ui-row:hover .ui-row__go { transform: translateX(2px); color: var(--rl-text); }

/* ---- tiles: the cards an index page lays out ---------------------------------------------------------------------------- */

.ui-tiles {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.85rem;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 17.5rem), 1fr));
}

.ui-tile {
    --tile-hue: 225;
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    min-width: 0;
    height: 100%;
    padding: 0.95rem 1rem 0.85rem;
    border: 1px solid var(--rl-border);
    border-radius: 14px;
    background: var(--rl-surface);
    color: inherit;
    box-shadow: var(--rl-shadow-sm);
    transition: border-color var(--rl-dur) var(--rl-ease), transform var(--rl-dur) var(--rl-ease), box-shadow var(--rl-dur) var(--rl-ease);
    animation: rl-rise 0.22s var(--rl-ease) both;
}

.ui-tile:hover { border-color: color-mix(in srgb, hsl(var(--tile-hue) 70% 55%) 55%, var(--rl-border)); transform: translateY(-2px); box-shadow: var(--rl-shadow-md); }
.ui-tile:focus-within { border-color: var(--rl-accent); }

/* A thin band of the tile's own colour along the top. */
.ui-tile::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    border-radius: 14px 14px 0 0;
    background: linear-gradient(90deg, hsl(var(--tile-hue) 75% 58%), hsl(calc(var(--tile-hue) + 50) 75% 50%));
    opacity: 0.85;
}

.ui-tile__top { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }

.ui-tile__icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 11px;
    background: linear-gradient(140deg, hsl(var(--tile-hue) 70% 55%), hsl(calc(var(--tile-hue) + 50) 70% 42%));
    color: #fff;
    font-weight: 750;
    font-size: 0.9rem;
    letter-spacing: 0.02em;
    box-shadow: 0 4px 12px hsl(var(--tile-hue) 60% 30% / 0.3);
    overflow: hidden;
}

.ui-tile__icon svg { width: 1.2rem; height: 1.2rem; }
.ui-tile__icon img { width: 100%; height: 100%; object-fit: cover; }

.ui-tile__name { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.05rem; }
.ui-tile__title { margin: 0; font-size: 0.97rem; font-weight: 650; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-tile__title a { color: inherit; text-decoration: none; }
.ui-tile__title a:focus-visible { outline: none; }
.ui-tile__kicker { color: var(--rl-text-muted); font-size: 0.74rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The title's link covers the whole tile; anything else clickable inside sits above it. */
.ui-tile__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.ui-tile button, .ui-tile .btn, .ui-tile a:not(.ui-tile__link), .ui-tile input, .ui-tile select, .ui-tile label, .ui-tile details { position: relative; z-index: 1; }

.ui-tile__desc {
    margin: 0;
    color: var(--rl-text-muted);
    font-size: 0.84rem;
    line-height: 1.45;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.ui-tile__desc--full { display: block; -webkit-line-clamp: unset; overflow: visible; }

.ui-tile__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.75rem;
    margin-top: auto;
    padding-top: 0.55rem;
    border-top: 1px solid var(--rl-border);
    color: var(--rl-text-muted);
    font-size: 0.76rem;
    font-variant-numeric: tabular-nums;
}

.ui-tile__foot > span { display: inline-flex; align-items: center; gap: 0.3rem; }
.ui-tile__foot svg { width: 0.85rem; height: 0.85rem; }
.ui-tile__actions { margin-left: auto; display: flex; gap: 0.3rem; }

/* A tile that starts a new one. */
.ui-tile--new { border-style: dashed; background: none; box-shadow: none; align-items: center; justify-content: center; text-align: center; color: var(--rl-text-muted); min-height: 8rem; cursor: pointer; font: inherit; }
.ui-tile--new::before { display: none; }
.ui-tile--new:hover { color: var(--rl-text); border-color: var(--rl-accent); }
.ui-tile--new svg { width: 1.4rem; height: 1.4rem; }

/* ---- chips, dots and avatars ------------------------------------------------------------------------------------------------ */

.ui-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.06rem 0.5rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--tone, var(--rl-text-muted)) 14%, transparent);
    color: var(--tone, var(--rl-text-muted));
    font-size: 0.72rem;
    font-weight: 650;
    line-height: 1.5;
    white-space: nowrap;
}

.ui-chip svg { width: 0.75rem; height: 0.75rem; }

.ui-dot { flex: none; display: inline-block; width: 0.55rem; height: 0.55rem; border-radius: 50%; background: var(--tone, var(--rl-text-muted)); }
.ui-dot--live { box-shadow: 0 0 0 0 color-mix(in srgb, var(--tone, var(--rl-ok)) 60%, transparent); animation: ui-ping 1.6s ease-out infinite; }

@keyframes ui-ping {
    70% { box-shadow: 0 0 0 0.45rem transparent; }
    100% { box-shadow: 0 0 0 0 transparent; }
}

.ui-avatar {
    --avatar-hue: 225;
    flex: none;
    display: grid;
    place-items: center;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 50%;
    background: linear-gradient(140deg, hsl(var(--avatar-hue) 65% 55%), hsl(calc(var(--avatar-hue) + 45) 65% 42%));
    color: #fff;
    font-size: 0.74rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    overflow: hidden;
}

.ui-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* An icon in a plain button, wherever it is: a page's own sizing still wins (:where keeps this rule's weight to one element). */
:where(.btn) > svg { width: 1rem; height: 1rem; flex: none; vertical-align: -0.17em; }

/* ---- switches, toolbars and tables -------------------------------------------------------------------------------------- */

/* The segmented switch: whose work, which view, which series. */
.ui-seg {
    display: inline-flex;
    flex-wrap: wrap;
    border: 1px solid var(--rl-border);
    border-radius: 999px;
    padding: 2px;
    background: var(--rl-surface-sunken);
}

.ui-seg button, .ui-seg a {
    border: 0;
    background: transparent;
    color: var(--rl-text-muted);
    font: inherit;
    font-size: 0.82rem;
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    transition: background var(--rl-dur) var(--rl-ease), color var(--rl-dur) var(--rl-ease);
}

.ui-seg button:hover, .ui-seg a:hover { color: var(--rl-text); }
.ui-seg button.is-on, .ui-seg a.is-on, .ui-seg a.active, .ui-seg [aria-pressed="true"], .ui-seg [aria-current="page"] { background: var(--rl-surface); color: var(--rl-text); box-shadow: var(--rl-shadow-sm); }
.ui-seg button:disabled { opacity: 0.45; cursor: not-allowed; }
.ui-seg button:focus-visible, .ui-seg a:focus-visible { outline: 2px solid var(--rl-accent); outline-offset: 1px; }

/* A row of filters over a list: a search box, a switch or two, a count on the right. */
.ui-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.65rem; margin: 0 0 1rem; }
.ui-toolbar__end { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; color: var(--rl-text-muted); font-size: 0.82rem; }

.ui-search { position: relative; flex: 1 1 16rem; max-width: 26rem; min-width: 0; }
.ui-search > svg { position: absolute; left: 0.75rem; top: 50%; width: 0.95rem; height: 0.95rem; transform: translateY(-50%); color: var(--rl-text-muted); pointer-events: none; }
.ui-search input {
    width: 100%;
    min-height: var(--rl-control-h, 2.25rem);
    padding: 0.35rem 0.85rem 0.35rem 2.2rem;
    border: 1px solid var(--rl-border);
    border-radius: 999px;
    background: var(--rl-surface);
    color: var(--rl-text);
    font: inherit;
    font-size: 0.9rem;
}

.ui-search input:focus-visible { outline: none; border-color: var(--rl-accent); box-shadow: var(--rl-ring); }

.ui-toolbar select {
    min-height: var(--rl-control-h, 2.25rem);
    padding: 0.3rem 0.75rem;
    border: 1px solid var(--rl-border);
    border-radius: 999px;
    background-color: var(--rl-surface);
    color: var(--rl-text);
    font: inherit;
    font-size: 0.86rem;
}

/* A table in a rounded frame, its header raised and small, as on the project page. */
.ui-table { overflow-x: auto; border: 1px solid var(--rl-border); border-radius: 10px; }
.ui-table .table { margin: 0; }
.ui-table .table th { background: var(--rl-surface-raised); font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase; white-space: nowrap; }
.ui-table .table td { vertical-align: middle; }
.ui-table .table tr:last-child td { border-bottom: 0; }
.ui-table .table tbody tr { transition: background var(--rl-dur) var(--rl-ease); }
.ui-table .table tbody tr:hover { background: color-mix(in srgb, var(--rl-surface-sunken) 60%, transparent); }

/* Fields laid out two or three abreast where they fit. */
.ui-form { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.ui-form .field { max-width: none; }
.ui-form__full { grid-column: 1 / -1; }

/* A strip of buttons at the foot of a form. */
.ui-formfoot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.5rem; padding-top: 0.75rem; border-top: 1px solid var(--rl-border); }
.ui-formfoot__note { margin-right: auto; color: var(--rl-text-muted); font-size: 0.82rem; }

@media (prefers-reduced-motion: reduce) {
    .hero, .hero__orb, .ui-tile, .ui-dot--live { animation: none; }
    .ui-tile, .ui-tile:hover { transition: none; transform: none; }
}
