/**
 * Kestrel components layer (template.kestrel.components): DESIGN_SPEC section 7 on the kit hooks
 * and the .ke-* names of PAGES.md 5, in the numbered sections below. The article and journal views
 * themselves are in views.css (K47).
 *
 * joomla.css (kit) prints after this file. Its baseline weighs (0,0,2) to (0,0,4), so every rule
 * here carries a class outside :where(); where Bootstrap draws the same element with a pseudo-class
 * or a link state, the rule carries one more class or the body prefix. The .ts-btn, .ts-tag and
 * .ts-badge hooks share the .ke-btn, .ke-chip and .ke-badge rules (one rule set, K40).
 *
 * @copyright Copyright (C) 2026 BulaSikku Technologies Private Limited. All rights reserved.
 * @license   GNU General Public License version 2 or later
 */

/* 0. Line icons drawn by CSS (Lucide geometry, stroke 1.9, DESIGN_SPEC 7.23). Painted through a
   mask in currentColor, so they follow the scheme and the scope. ------------------------------- */

:root {
    --ke-i-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    --ke-i-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m13 6 6 6-6 6'/%3E%3C/svg%3E");
    --ke-i-alert: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5'/%3E%3Cpath d='M12 16.2v.01'/%3E%3C/svg%3E");
    --ke-i-lock: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='11' width='16' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
    --ke-i-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}

/* 1. Buttons (DESIGN_SPEC 7.1, K22): 48px, 8px radius, 15/600; the modifier picks the fill.
   .ts-btn is the kit's primary, .ts-btn--outline its secondary. ----------------------------------- */

:is(.ke-btn, .ts-btn) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.625rem;
    min-block-size: var(--ke-control-h);
    max-inline-size: 100%;
    margin: 0;
    padding: 0.5rem var(--ts-btn-pad-x, 1.375rem);
    border: 1px solid var(--ke-accent);
    border-radius: var(--ke-r-control);
    background-color: var(--ke-accent);
    color: var(--ke-on-accent);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    line-height: 1.25;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--ec-dur-1) var(--ec-ease), border-color var(--ec-dur-1) var(--ec-ease), color var(--ec-dur-1) var(--ec-ease);
}

:is(.ke-btn, .ts-btn):is(:hover, :focus-visible) {
    border-color: var(--ke-accent-hover);
    background-color: var(--ke-accent-hover);
    color: var(--ke-on-accent);
    text-decoration: none;
}

:is(.ke-btn, .ts-btn) > svg {
    flex: none;
    inline-size: 1.125rem;
    block-size: 1.125rem;
}

.ke-btn.ke-btn--ink {
    border-color: var(--ke-ink);
    background-color: var(--ke-ink);
    color: var(--ke-on-ink);
}

.ke-btn.ke-btn--ink:is(:hover, :focus-visible) {
    border-color: var(--ke-ink-hover);
    background-color: var(--ke-ink-hover);
    color: var(--ke-on-ink);
}

:is(.ke-btn.ke-btn--outline, .ts-btn.ts-btn--outline) {
    border-color: var(--ke-ink);
    background-color: var(--ke-page);
    color: var(--ke-ink);
}

:is(.ke-btn.ke-btn--outline, .ts-btn.ts-btn--outline):is(:hover, :focus-visible) {
    border-color: var(--ke-ink);
    background-color: var(--ke-paper);
    color: var(--ke-ink);
}

.ke-btn.ke-btn--danger {
    border-color: var(--ke-danger);
    background-color: var(--ke-danger);
    color: var(--ke-on-danger);
}

.ke-btn.ke-btn--danger:is(:hover, :focus-visible) {
    border-color: var(--ke-danger-ink);
    background-color: var(--ke-danger-ink);
    color: var(--ke-on-danger);
}

/* Compact: 44px, 0 16px, 14/600, icon 16. */
:is(.ke-btn, .ts-btn).ke-btn--sm {
    gap: 0.5rem;
    min-block-size: var(--ke-control-h-sm);
    padding-inline: 1rem;
    font-size: var(--ke-t-label);
}

:is(.ke-btn, .ts-btn).ke-btn--sm > svg {
    inline-size: 1rem;
    block-size: 1rem;
}

.ke-btn.ke-btn--block {
    inline-size: 100%;
}

/* (0,3,0) through the :hover arguments, so no variant's hover state reaches a disabled button. */
:is(.ke-btn, .ts-btn):is(:disabled, [aria-disabled="true"], :disabled:hover, [aria-disabled="true"]:hover) {
    border-color: var(--ke-disabled-bg);
    background-color: var(--ke-disabled-bg);
    color: var(--ke-disabled-fg);
    cursor: not-allowed;
}

/* Quiet link and the module "more" link (M::more(), PAGES.md 2.7): 44px, ink 15/600, arrow 16. */
:is(.ke-btn.ke-btn--quiet, .ts-more) {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-block-size: var(--ke-control-h-sm);
    padding: 0;
    border: 0;
    background: none;
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    line-height: 1.25;
    text-decoration: none;
}

:is(.ke-btn.ke-btn--quiet, .ts-more):is(:hover, :focus-visible) {
    border: 0;
    background: none;
    color: var(--ke-ink);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.ts-more > svg {
    flex: none;
    inline-size: 1rem;
    block-size: 1rem;
}

.ts-sec__more {
    margin: 0;
}

/* Icon buttons: 44 by 44, icon 18; the plain form has no frame (header toggles live in layout.css). */
.ke-iconbtn {
    display: inline-grid;
    place-items: center;
    flex: none;
    inline-size: var(--ke-control-h-sm);
    block-size: var(--ke-control-h-sm);
    margin: 0;
    padding: 0;
    border: 1px solid var(--ke-hairline);
    border-radius: var(--ke-r-control);
    background-color: var(--ke-page);
    color: var(--ke-ink);
    cursor: pointer;
    transition: background-color var(--ec-dur-1) var(--ec-ease);
}

.ke-iconbtn.ke-iconbtn--plain {
    border-color: transparent;
    background-color: transparent;
}

.ke-iconbtn:hover {
    background-color: var(--ke-paper);
    color: var(--ke-ink);
}

.ke-iconbtn > svg {
    inline-size: 1.125rem;
    block-size: 1.125rem;
}

/* 2. Toggle buttons (DESIGN_SPEC 7.2): 44px, 0 16px, ink outline off, accent tint on. --------- */

.ke-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-block-size: var(--ke-control-h-sm);
    margin: 0;
    padding: 0 1rem;
    border: 1px solid var(--ke-ink);
    border-radius: var(--ke-r-control);
    background-color: var(--ke-page);
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    line-height: 1.25;
    cursor: pointer;
    transition: background-color var(--ec-dur-1) var(--ec-ease), border-color var(--ec-dur-1) var(--ec-ease);
}

.ke-toggle:hover {
    background-color: var(--ke-paper);
}

.ke-toggle[aria-pressed="true"] {
    border-color: var(--ke-accent-line);
    background-color: var(--ke-accent-soft);
    color: var(--ke-ink);
}

.ke-toggle > svg {
    flex: none;
    inline-size: 1.125rem;
    block-size: 1.125rem;
}

/* 3. Fields (DESIGN_SPEC 7.3, DV1, DV2): 48px, 0 14px, 16px ink on the raised fill, the control
   border; focus adds the accent border and a 3px tint halo inside the 2px ring of base.css. ---- */

:is(.ts-field, .ke-field) {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-inline-size: 0;
    margin: 0;
}

:is(.ts-field, .ke-field, .ts-modlogin__field) > :is(label, .form-label),
:is(.ts-auth, .ts-profile, .ts-finder, .ts-offline, .ke-offline, .ke-error) :is(.form-label, .control-label > label) {
    display: block;
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-label);
    font-weight: 600;
    line-height: var(--ke-lh-label);
}

:is(.ts-field, .ke-field, .ts-modlogin__field, .control-group) .star {
    color: var(--ke-danger);
}

:is(.ke-field__help, .ts-field__help, .form-text) {
    margin: 0;
    color: var(--ke-ink-3);
    font-size: var(--ke-t-help);
    line-height: var(--ke-lh-help);
}

html .ts-input,
html .ke-input,
:is(.ts-auth, .ts-profile, .ts-finder, .ts-offline, .ke-offline, .ke-error) :is(.form-control, .form-select) {
    display: block;
    inline-size: 100%;
    min-inline-size: 0;
    min-block-size: var(--ke-control-h);
    margin: 0;
    padding: 0.6875rem 0.875rem;
    border: 1px solid var(--ke-control);
    border-radius: var(--ke-r-control);
    background-color: var(--ke-raised);
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-body);
    font-weight: 400;
    line-height: 1.5;
    box-shadow: none;
    transition: border-color var(--ec-dur-1) var(--ec-ease), box-shadow var(--ec-dur-1) var(--ec-ease);
}

:is(.ts-input, .ke-input)::placeholder,
:is(.ts-auth, .ts-profile, .ts-finder, .ts-offline, .ke-offline, .ke-error) .form-control::placeholder {
    color: var(--ke-ink-3);
    opacity: 1;
}

body :is(.ts-input, .ke-input):focus,
body :is(.ts-auth, .ts-profile, .ts-finder, .ts-offline, .ke-offline, .ke-error) :is(.form-control, .form-select):focus {
    border-color: var(--ke-accent);
    background-color: var(--ke-raised);
    box-shadow: 0 0 0 var(--ke-halo-w) var(--ke-accent-halo);
}

body :is(.ts-input, .ke-input):is([aria-invalid="true"], .invalid),
body .ts-field[data-state="error"] .ts-input,
body :is(.ts-auth, .ts-profile, .ts-offline) :is(.form-control, .form-select):is([aria-invalid="true"], .invalid) {
    border-color: var(--ke-danger);
    box-shadow: 0 0 0 var(--ke-halo-w) var(--ke-danger-soft);
}

body :is(.ts-input, .ke-input):is(:disabled, [readonly]),
body :is(.ts-auth, .ts-profile, .ts-offline) :is(.form-control, .form-select):is(:disabled, [readonly]) {
    border-color: var(--ke-hairline);
    background-color: var(--ke-paper);
    color: var(--ke-ink-3);
}

/* The label of a disabled or read-only field drops to ink 3 with it (DESIGN_SPEC 7.3). */
:is(.ts-field, .ke-field):has(> :is(.ts-input, .ke-input):is(:disabled, [readonly])) > :is(label, .form-label) {
    color: var(--ke-ink-3);
}

select:is(.ts-input, .ke-input),
:is(.ts-auth, .ts-profile, .ts-finder) .form-select {
    appearance: none;
    padding-inline: 0.875rem 2.5rem;
    background-image: var(--ts-mark-chevron);
    background-repeat: no-repeat;
    background-position: right 0.875rem center;
    background-size: 1rem 0.75rem;
}

textarea:is(.ts-input, .ke-input),
:is(.ts-auth, .ts-profile) textarea.form-control {
    min-block-size: 8.75rem;
    padding-block: 0.75rem;
    line-height: 1.5;
    resize: vertical;
}

/* Error text in words, tied to the field (Joomla validate.js and the kit's .ts-field state). */
:is(.ke-field__error, .ts-field__error, .form-control-feedback) {
    display: flex;
    align-items: flex-start;
    gap: 0.375rem;
    margin: 0;
    color: var(--ke-danger);
    font-size: var(--ke-t-help);
    line-height: var(--ke-lh-help);
}

:is(.ke-field__error, .ts-field__error, .form-control-feedback)::before {
    content: "";
    flex: none;
    inline-size: 1rem;
    block-size: 1rem;
    margin-block-start: 0.0625rem;
    background-color: currentColor;
    -webkit-mask: var(--ke-i-alert) center / contain no-repeat;
    mask: var(--ke-i-alert) center / contain no-repeat;
}

/* Checks and radios: 20px native marks in a 44px row, label 15px (Bootstrap's float layout off). */
.ts-check,
.ke-check {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
    min-block-size: var(--ke-control-h-sm);
    margin: 0;
    padding: 0;
    color: var(--ke-ink);
    font-size: var(--ke-t-ui);
    line-height: 1.4;
}

:is(.ts-check, .ke-check) > :is(.form-check-input, input[type="checkbox"], input[type="radio"]) {
    float: none;
    flex: none;
    inline-size: 1.25rem;
    block-size: 1.25rem;
    margin: 0;
}

:is(.ts-check, .ke-check) > :is(.form-check-input, input[type="checkbox"], input[type="radio"]):not(:checked) {
    border-color: var(--ke-control);
}

:is(.ts-check, .ke-check) > :is(label, .form-check-label) {
    margin: 0;
    color: var(--ke-ink);
    font-size: var(--ke-t-ui);
    font-weight: 400;
    cursor: pointer;
}

/* The core password reveal button inside the field (Joomla .input-password-toggle, kit login). */
.ts-modlogin__control,
.ke-password {
    position: relative;
    min-inline-size: 0;
}

:is(.ts-modlogin__control, .ke-password):has(.input-password-toggle) > .ts-input {
    padding-inline-end: 3.5rem;
}

:is(.ts-modlogin__control, .ke-password) > .input-password-toggle {
    position: absolute;
    inset-block-start: 0.125rem;
    inset-inline-end: 0.125rem;
    display: inline-grid;
    place-items: center;
    inline-size: var(--ke-control-h-sm);
    min-inline-size: var(--ke-control-h-sm);
    block-size: var(--ke-control-h-sm);
    min-block-size: var(--ke-control-h-sm);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--ke-r-sm);
    background-color: transparent;
    color: var(--ke-ink-2);
    font-size: 1.125rem;
    cursor: pointer;
}

:is(.ts-modlogin__control, .ke-password) > .input-password-toggle:hover {
    background-color: var(--ke-paper);
    color: var(--ke-ink);
}

/* The login module (kit mod_login): labelled fields, icons inside, full-width submit. */
.ts-modlogin,
.ts-modlogout,
.ts-modlogin__userdata {
    display: flex;
    flex-direction: column;
    gap: 1.125rem;
    min-inline-size: 0;
    margin: 0;
    font-family: var(--ke-sans);
}

.ts-modlogin__field {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.ts-modlogin__control > .ts-modlogin__icon {
    position: absolute;
    inset-block-start: 0.9375rem;
    inset-inline-start: 0.875rem;
    inline-size: 1.125rem;
    block-size: 1.125rem;
    color: var(--ke-ink-3);
    pointer-events: none;
}

.ts-modlogin__control:has(> .ts-modlogin__icon) > .ts-input {
    padding-inline-start: 2.625rem;
}

:is(.ts-modlogin__submit, .ts-modlogout__submit) > .ts-btn,
.ts-modlogout__btn {
    inline-size: 100%;
}

.ts-modlogin__options,
.ts-modlogout__options {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

:is(.ts-modlogin__options, .ts-modlogout__options) > li {
    margin: 0;
    border-block-end: 1px solid var(--ke-hairline);
}

:is(.ts-modlogin__options, .ts-modlogout__options) a {
    display: flex;
    align-items: center;
    min-block-size: var(--ke-control-h-sm);
    color: var(--ke-ink);
    font-size: var(--ke-t-ui);
    font-weight: 500;
    text-decoration: none;
}

:is(.ts-modlogin__options, .ts-modlogout__options) a:hover {
    color: var(--ke-ink);
    text-decoration: underline;
}

.ts-modlogin__divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: var(--ke-track-meta);
    text-transform: uppercase;
}

.ts-modlogin__divider::before,
.ts-modlogin__divider::after {
    content: "";
    flex: 1;
    block-size: 1px;
    background-color: var(--ke-hairline);
}

:is(.ts-modlogin__pretext, .ts-modlogin__posttext, .ts-modlogout__greeting) {
    margin: 0;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-ui);
    line-height: 1.55;
}

/* 4. System messages (DESIGN_SPEC 7.4): the kit's joomla-alert skin, coloured per status; no
   status bar (--ts-alert-bar-width is 0px). (0,0,2) beats the kit's custom property defaults. ---- */

body joomla-alert {
    --jui-alert-padding: 0.875rem 1rem;
    --jui-alert-border-radius: var(--ke-r);
    --jui-alert-success-color: var(--ke-success-ink);
    --jui-alert-success-background-color: var(--ke-success-soft);
    --jui-alert-success-border-color: var(--ke-success-line);
    --jui-alert-success-link-color: var(--ke-success-ink);
    --jui-alert-info-color: var(--ke-ink);
    --jui-alert-info-background-color: var(--ke-accent-soft);
    --jui-alert-info-border-color: var(--ke-accent-line);
    --jui-alert-info-link-color: var(--ke-ink);
    --jui-alert-warning-color: var(--ke-warning-ink);
    --jui-alert-warning-background-color: var(--ke-warning-soft);
    --jui-alert-warning-border-color: var(--ke-warning-line);
    --jui-alert-warning-link-color: var(--ke-warning-ink);
    --jui-alert-danger-color: var(--ke-danger-ink);
    --jui-alert-danger-background-color: var(--ke-danger-soft);
    --jui-alert-danger-border-color: var(--ke-danger-line);
    --jui-alert-danger-link-color: var(--ke-danger-ink);
    --jui-alert-button-color-dark: currentColor;
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    line-height: 1.5;
}

body joomla-alert[type="info"] {
    --ts-alert-accent: var(--ke-accent);
}

body joomla-alert[type="success"] {
    --ts-alert-accent: var(--ke-success);
}

body joomla-alert[type="warning"] {
    --ts-alert-accent: var(--ke-warning);
}

body joomla-alert[type="danger"] {
    --ts-alert-accent: var(--ke-danger);
}

body joomla-alert > .alert-heading {
    block-size: 1.375rem;
}

/* Warning and error take the alert circle of DESIGN_SPEC 7.4 (the kit draws a triangle and a
   cross), at the stroke of the kit's other message icons. */
body joomla-alert > .alert-heading > :is(.warning, .error, .danger) {
    --ts-alert-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3e%3ccircle cx='12' cy='12' r='9.5'/%3e%3cpath d='M12 7.5V13M12 16.5h.01'/%3e%3c/svg%3e");
}

body joomla-alert :is(.joomla-alert--close, .joomla-alert-button--close) {
    border-radius: var(--ke-r-sm);
    color: inherit;
    font-size: 1.25rem;
    opacity: 1;
}

/* Inline notices inside components (DESIGN_SPEC 7.4): same colours, compact. */
.ke-notice {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0;
    padding: 0.4375rem 0.75rem;
    border: 1px solid var(--ke-accent-line);
    border-radius: var(--ke-r-sm);
    background-color: var(--ke-accent-soft);
    color: var(--ke-ink);
    font-size: var(--ke-t-label);
    line-height: 1.4;
}

.ke-notice.ke-notice--success {
    border-color: var(--ke-success-line);
    background-color: var(--ke-success-soft);
    color: var(--ke-success-ink);
}

.ke-notice.ke-notice--warning {
    border-color: var(--ke-warning-line);
    background-color: var(--ke-warning-soft);
    color: var(--ke-warning-ink);
}

.ke-notice.ke-notice--danger {
    border-color: var(--ke-danger-line);
    background-color: var(--ke-danger-soft);
    color: var(--ke-danger-ink);
}

/* 5. Breadcrumbs (DESIGN_SPEC 7.5, PAGES.md 2.5): mono 12 caps, ink 2 links, "/" separators. -- */

.ts-breadcrumbs {
    margin: 0;
    font-family: var(--ke-mono);
}

.ts-breadcrumbs__here {
    position: absolute !important;
    inline-size: 1px !important;
    block-size: 1px !important;
    margin: -1px !important;
    padding: 0 !important;
    overflow: hidden !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
}

.ts-breadcrumbs .ts-breadcrumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem 0.625rem;
    margin: 0;
    padding: 0;
    background: none;
    list-style: none;
    font-size: var(--ke-t-meta);
    line-height: 1.3;
    letter-spacing: var(--ke-track-index);
    text-transform: uppercase;
}

.ts-breadcrumbs .ts-breadcrumbs__item {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    margin: 0;
    padding: 0;
    color: var(--ke-ink-2);
}

.ts-breadcrumbs .ts-breadcrumbs__item + .ts-breadcrumbs__item {
    padding-inline-start: 0;
}

/* The "/" trails its item (Bootstrap's leading divider goes), so a trail that wraps ends the line
   with it and the next line starts with a crumb, as Article-390 draws it. */
.ts-breadcrumbs .ts-breadcrumbs__item + .ts-breadcrumbs__item::before {
    content: none;
    float: none;
    padding: 0;
}

.ts-breadcrumbs .ts-breadcrumbs__item:not(:last-child)::after {
    content: "/" / "";
    color: var(--ke-ink-3);
}

.ts-breadcrumbs__item > .pathway {
    display: inline-flex;
    align-items: center;
    min-block-size: 2rem;
    color: var(--ke-ink-2);
    text-decoration: none;
}

.ts-breadcrumbs__item > .pathway:hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ts-breadcrumbs .ts-breadcrumbs__item--current {
    color: var(--ke-ink);
}

/* 6. Pagination (DESIGN_SPEC 7.6): 44px tiles, hairline, ink current tile, mono counter. -------- */

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.25rem;
    margin: 0;
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) .pagination {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ts-page-gap, 0.5rem);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Core prints nav.pagination__wrapper > ul.pagination.ms-0.mb-4 inside the kit pager: the pager
   owns the spacing, so the wrapper's baseline margins (joomla.css) and Bootstrap's !important
   utility margin go, and the counter centres on the tiles. */
:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) .pagination__wrapper {
    margin: 0;
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) .pagination.mb-4 {
    margin-block-end: 0 !important;
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) .page-item {
    margin: 0;
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) .page-link {
    display: inline-grid;
    place-items: center;
    min-inline-size: var(--ke-control-h-sm);
    min-block-size: var(--ke-control-h-sm);
    margin: 0;
    padding: 0 0.75rem;
    border: 1px solid var(--ke-hairline);
    border-radius: var(--ke-r-control);
    background-color: var(--ke-page);
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    text-decoration: none;
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) a.page-link:hover {
    border-color: var(--ke-ink);
    background-color: var(--ke-paper);
    color: var(--ke-ink);
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) :is(.active > .page-link, .page-link[aria-current="page"]) {
    border-color: var(--ke-ink);
    background-color: var(--ke-ink);
    color: var(--ke-on-ink);
}

:is(.ts-pager, .ts-tags-pagination, .ts-finder__navigation, .ke-pager) .disabled > .page-link {
    border-color: var(--ke-hairline);
    background-color: var(--ke-page);
    color: var(--ke-ink-3);
}

/* (0,2,0): the core counter classes beside the kit's (.com-content-category-blog__counter and its
   twins in joomla.css, 14px in fg 2) print later at (0,1,0). */
:is(.ts-pager, .ts-tags-pagination, .ke-pager) :is(.ts-pager__counter, .ts-tags-pagination__counter, .ke-pager__counter) {
    margin: 0;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: var(--ke-track-meta);
    font-variant-numeric: tabular-nums;
}

/* 7. Tabs (DESIGN_SPEC 7.7): 2px accent underline on the selected tab, hairline under the list. - */

.ke-tabs {
    display: flex;
    gap: 1.75rem;
    margin: 0;
    padding: 0;
    overflow-x: auto;
    border-block-end: 1px solid var(--ke-hairline);
    list-style: none;
    scrollbar-width: none;
}

.ke-tabs__tab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    flex: none;
    min-block-size: var(--ke-control-h);
    margin: 0 0 -1px;
    padding: 0.75rem 0 0.625rem;
    border: 0;
    border-block-end: 2px solid transparent;
    background: none;
    color: var(--ke-ink-2);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    font-weight: 500;
    line-height: 1.33;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

.ke-tabs__tab:hover {
    color: var(--ke-ink);
}

.ke-tabs__tab:is([aria-selected="true"], [aria-current="page"]) {
    border-block-end-color: var(--ts-signal);
    color: var(--ke-ink);
    font-weight: 600;
}

.ke-tabs__count {
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    font-weight: 500;
}

/* 8. Chips (DESIGN_SPEC 7.8): 36px pills on paper; current in ink; the "All tags" link chip. -- */

:is(.ke-chips, .ke-subnav, .ke-sections) {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

:is(.ke-chips, .ke-subnav, .ke-sections) > li {
    margin: 0;
}

.ke-chip,
.ts-tag,
.ke-sections a,
:is(.ke-tags, .ts-article__tags) .tags a {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-block-size: var(--ke-chip-h);
    margin: 0;
    padding: 0 0.875rem;
    border: 1px solid var(--ke-hairline);
    border-radius: var(--ke-pill);
    background-color: var(--ke-paper);
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-label);
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;
    transition: background-color var(--ec-dur-1) var(--ec-ease), border-color var(--ec-dur-1) var(--ec-ease);
}

a.ke-chip:hover,
a.ts-tag:hover,
.ke-sections a:hover,
:is(.ke-tags, .ts-article__tags) .tags a:hover {
    border-color: var(--ke-ink);
    color: var(--ke-ink);
    text-decoration: none;
}

:is(.ke-chip, .ke-sections a):is([aria-current="page"], .ke-chip--current) {
    border-color: var(--ke-ink);
    background-color: var(--ke-ink);
    color: var(--ke-on-ink);
}

:is(.ke-chip__count, .ke-sections__count) {
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}

:is(.ke-chip, .ke-sections a):is([aria-current="page"], .ke-chip--current) :is(.ke-chip__count, .ke-sections__count) {
    color: inherit;
}

.ke-chip.ke-chip--link {
    gap: 0.375rem;
    padding-inline: 0.25rem;
    border-color: transparent;
    background-color: transparent;
    color: var(--ts-link);
    font-weight: 600;
}

.ke-chip.ke-chip--link:hover {
    border-color: transparent;
    color: var(--ts-link-hover);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ke-chip.ke-chip--link::after {
    content: "";
    inline-size: 0.875rem;
    block-size: 0.875rem;
    background-color: currentColor;
    -webkit-mask: var(--ke-i-arrow) center / contain no-repeat;
    mask: var(--ke-i-arrow) center / contain no-repeat;
}

/* Joomla tag lists inside Kestrel pieces read as chips. */
:is(.ke-tags, .ts-article__tags) .tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

:is(.ke-tags, .ts-article__tags) .tags > li {
    margin: 0;
}

/* 9. Badges (DESIGN_SPEC 7.9): 24px, mono 11 caps, 4px radius; the kit's .ts-badge and "You". -- */

:is(.ke-badge, .ts-badge) {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-block-size: var(--ke-badge-h);
    margin: 0;
    padding: 0 0.5rem;
    border: 1px solid var(--ke-hairline);
    border-radius: var(--ts-badge-radius, var(--ke-r-xs));
    background-color: var(--ke-paper);
    color: var(--ke-ink-2);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-micro);
    font-weight: 500;
    line-height: 1;
    letter-spacing: var(--ke-track-index);
    text-transform: uppercase;
    white-space: nowrap;
}

:is(.ke-badge, .ts-badge) > svg {
    flex: none;
    inline-size: 0.75rem;
    block-size: 0.75rem;
}

.ke-badge.ke-badge--tint {
    border-color: var(--ke-accent-line);
    background-color: var(--ke-accent-soft);
    color: var(--ke-ink);
}

.ke-badge.ke-badge--rare {
    border-color: var(--ke-accent);
    background-color: var(--ke-accent-soft);
    color: var(--ke-ink);
}

.ke-badge.ke-badge--ok {
    border-color: var(--ke-success-line);
    background-color: var(--ke-success-soft);
    color: var(--ke-success-ink);
}

:is(.ke-badge.ke-badge--warn, .ts-badge.ts-badge--stock) {
    border-color: var(--ke-warning-line);
    background-color: var(--ke-warning-soft);
    color: var(--ke-warning-ink);
}

.ke-badge.ke-badge--err {
    border-color: var(--ke-danger-line);
    background-color: var(--ke-danger-soft);
    color: var(--ke-danger-ink);
}

:is(.ke-badge.ke-badge--you, .ts-tag.ts-tag--you) {
    min-block-size: 1.25rem;
    padding: 0 0.375rem;
    border: 0;
    border-radius: var(--ke-r-xs);
    background-color: var(--ke-accent);
    color: var(--ke-on-accent);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-micro);
    font-weight: 600;
    letter-spacing: var(--ke-track-index);
    text-transform: uppercase;
}

/* 10. Heads, cards and story rows (DESIGN_SPEC 5.3, 7.10) ---------------------------------------- */

:is(.ke-eyebrow, .ts-articles__eyebrow) {
    margin: 0;
    color: var(--ts-link);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-eyebrow);
    font-weight: 600;
    line-height: var(--ke-lh-label);
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
}

.ke-note {
    margin: 0;
    color: var(--ke-ink-3);
    font-size: var(--ke-t-help);
    line-height: var(--ke-lh-help);
}

/* The rule head shared by the featured head and kestrel:more (header.ke-head). */
.ke-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem 1.5rem;
    margin: 0 0 2rem;
    padding-block-start: 0.875rem;
    border-block-start: 2px solid var(--ke-rule);
}

:is(.ke-head__title, .ts-sec__title) {
    display: flex;
    align-items: baseline;
    column-gap: 0.875rem;
    min-inline-size: 0;
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-h2);
    font-weight: var(--ke-w-h2);
    line-height: var(--ke-lh-h2);
    letter-spacing: var(--ke-track-h2);
    font-synthesis-weight: none;
    text-wrap: balance;
    overflow-wrap: break-word;
}

.ke-sec__index {
    flex: none;
    color: var(--ts-link);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-index);
    font-weight: 500;
    line-height: 1;
    letter-spacing: var(--ke-track-index);
    font-variant-numeric: tabular-nums;
}

/* Teaser cards (kestrel:more): image 3:2, eyebrow, title 23, excerpt 15, meta mono. */
.ke-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(max(min(var(--ke-card-min), 100%), (100% - (var(--ec-grid, 3) - 1) * 2rem) / var(--ec-grid, 3)), 1fr));
    gap: 3rem 2rem;
}

.ke-card {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    min-inline-size: 0;
}

.ke-card__media {
    display: block;
    aspect-ratio: 3 / 2;
    overflow: hidden;
    border-radius: var(--ke-r-img);
    background-color: var(--ke-paper);
}

.ke-card__media > img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

:is(.ke-card__title, .ts-articles__title) {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-h3);
    font-weight: var(--ke-w-h3);
    line-height: var(--ke-lh-h3);
    letter-spacing: var(--ke-track-h3);
    text-wrap: balance;
}

:is(.ke-card__title, .ke-guide__title, .ke-rank__title, .ke-event__title, .ts-articles__title, .ts-articles__eyebrow) > a {
    color: inherit;
    text-decoration: none;
}

:is(.ke-card__title, .ke-guide__title, .ke-rank__title, .ke-event__title, .ts-articles__title, .ts-articles__eyebrow) > a:hover {
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

:is(.ke-card__text, .ts-articles__excerpt) {
    margin: 0;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-ui);
    line-height: var(--ke-lh-body);
    text-wrap: pretty;
}

:is(.ke-card__meta, .ke-guide__meta, .ke-rank__meta, .ts-articles__meta) {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem calc(1.25rem + 1ch);
    margin: 0;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    line-height: 1.4;
    letter-spacing: var(--ke-track-meta);
    clip-path: inset(-0.5rem -0.375rem);
}

/* Guide cards (kestrel:guides): the module rule, label "Guide 01", title 23, meta mono. */
.ke-guides {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(17.5rem, 100%), 1fr));
    gap: 2.5rem 2rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ke-guide {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    min-inline-size: 0;
    margin: 0;
    padding-block-start: 1rem;
    border-block-start: 2px solid var(--ke-rule);
}

.ke-guide__title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-h3);
    font-weight: var(--ke-w-h3);
    line-height: var(--ke-lh-h3);
    letter-spacing: var(--ke-track-h3);
    text-wrap: balance;
}

/* Ranked rows (kestrel:popular): Bricolage 44 numeral in the link colour, hairline below. */
.ke-rank {
    margin: 0;
    padding: 0;
    list-style: none;
}

.ke-rank__item {
    display: grid;
    grid-template-columns: 3.5rem minmax(0, 1fr);
    gap: 0.25rem 1rem;
    align-items: baseline;
    margin: 0;
    padding: 1.375rem 0;
    border-block-end: 1px solid var(--ke-hairline);
}

.ke-rank__num {
    grid-row: span 2;
    color: var(--ts-link);
    font-family: var(--ke-display);
    font-size: var(--ke-t-num);
    font-weight: 700;
    line-height: 0.9;
    letter-spacing: var(--ke-track-page);
}

.ke-rank__title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-list);
    font-weight: var(--ke-w-h3);
    line-height: var(--ke-lh-list);
    letter-spacing: var(--ke-track-list);
}

/* Link rows in side modules (kestrel:related, kestrel:months, a side mod_menu). */
:is(.ke-related, .ke-months) {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

:is(.ke-related, .ke-months) > li {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: 0;
    padding: 0.875rem 0;
    border-block-end: 1px solid var(--ke-hairline);
}

.ke-related__cat {
    margin: 0;
    color: var(--ts-link);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-eyebrow);
    font-weight: 600;
    line-height: var(--ke-lh-label);
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
}

:is(.ke-related__link, .ke-months__link) {
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-row);
    font-weight: var(--ke-w-h3);
    line-height: 1.3;
    letter-spacing: var(--ke-track-list);
    text-decoration: none;
}

:is(.ke-related__link, .ke-months__link):hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Months read as plain rows (Archive board): 15/500 sans, the month being read in the accent. */
.ke-months > li > .ke-months__link {
    font-family: var(--ke-sans);
    font-size: var(--ke-t-ui);
    font-weight: 500;
    letter-spacing: 0;
}

.ke-months > li > .ke-months__link[aria-current="page"] {
    color: var(--ts-link);
    font-weight: 600;
}

/* Paper panels (kestrel:panel): a paper scope, so its ground is var(--ke-page) inside it. */
.ke-panel {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    margin: 0;
    padding: 1.75rem;
    border-radius: var(--ke-r);
    background-color: var(--ke-page);
    color: var(--ke-ink);
}

.ke-panel :is(h2, h3) {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-panel);
    font-weight: var(--ke-w-h2);
    line-height: var(--ke-lh-panel);
    letter-spacing: var(--ke-track-h2);
    text-wrap: balance;
}

.ke-panel p {
    margin: 0;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-ui);
    line-height: var(--ke-lh-body);
}

.ke-panel p.ke-eyebrow {
    color: var(--ts-link);
    font-size: var(--ke-t-eyebrow);
    line-height: var(--ke-lh-label);
}

.ke-panel p:has(> a:only-child) {
    margin-block-start: 0.375rem;
}

.ke-panel p:has(> a:only-child) > a {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    min-block-size: var(--ke-control-h);
    padding: 0 1.375rem;
    border-radius: var(--ke-r-control);
    background-color: var(--ke-accent);
    color: var(--ke-on-accent);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    text-decoration: none;
}

.ke-panel p:has(> a:only-child) > a:hover {
    background-color: var(--ke-accent-hover);
    color: var(--ke-on-accent);
}

/* The panel's rule list (PAGES.md 3.9, README H3). */
.ke-rules {
    margin: 0;
    padding: 0;
    border-block-start: 1px solid var(--ke-hairline);
    list-style: none;
}

.ke-rules__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding-block: 0.875rem;
    border-block-end: 1px solid var(--ke-hairline);
}

.ke-rules__what {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-inline-size: 0;
    font-size: var(--ke-t-ui);
    font-weight: 600;
    line-height: 1.4;
}

.ke-rules__limit {
    color: var(--ke-ink-3);
    font-size: var(--ke-t-help);
    font-weight: 400;
    line-height: var(--ke-lh-help);
}

.ke-rules__value {
    display: inline-flex;
    flex: none;
    align-items: baseline;
    gap: 0.375rem;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: var(--ke-track-meta);
}

.ke-rules__value > strong {
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: 1.625rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
}

/* 11. Section and sidebar module chromes (PAGES.md 1.3, 2.7; DESIGN_SPEC 5.3, 7.11) -------------
   keSection and tsSection: the 2px ink rule head, the layout's p.ts-sec__more lifted into the head
   row. tsCard, tsPanel (K38) and a titled tsClean: the mono module head under the rule, no box.
   tsBare: nothing. The band variant (row "band", a paper scope) paints the full-bleed paper. */

.ts-sec {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "head more";
    column-gap: 1.5rem;
    min-inline-size: 0;
    margin: 0;
    padding-block-start: 0.875rem;
    border-block-start: 2px solid var(--ke-rule);
}

/* The sub sits at the right of the title while there is room (StyleGuide section heads). */
.ts-sec > .ts-sec__head {
    grid-area: head;
    align-self: baseline;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.375rem 1.5rem;
    min-inline-size: 0;
    margin-block-end: var(--ke-sec-gap, 2rem);
}

.ts-sec > .ts-sec__body {
    display: contents;
}

.ts-sec > .ts-sec__body > *,
.ts-sec > .ts-sec__body > .mod-custom:has(> .ts-sec__more) > * {
    grid-column: 1 / -1;
    min-inline-size: 0;
}

.ts-sec > .ts-sec__body > .mod-custom:has(> .ts-sec__more) {
    display: contents;
}

.ts-sec > .ts-sec__body > .ts-sec__more,
.ts-sec > .ts-sec__body > .mod-custom > .ts-sec__more {
    grid-area: more;
    align-self: baseline;
    margin: 0;
}

/* A ruled list follows the head 8px down: its rows carry their own padding (DESIGN_SPEC 5.2). */
.ts-sec:has(> .ts-sec__body > :is(.ke-rank, .ke-feed, .ke-surveys, .ke-events, .ke-related, .ke-leaders__list)) {
    --ke-sec-gap: 0.5rem;
}

/* Phones (MemberHome-390): the more link drops 8px under the title. */
@media (width < 30rem) {
    .ts-sec {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: "head" "more";
    }

    .ts-sec > .ts-sec__body > .ts-sec__more,
    .ts-sec > .ts-sec__body > .mod-custom > .ts-sec__more {
        margin-block: calc(0.5rem - var(--ke-sec-gap, 2rem)) var(--ke-sec-gap, 2rem);
    }
}

.ts-sec__sub {
    margin: 0;
    color: var(--ke-ink-3);
    font-size: var(--ke-t-ui);
    line-height: 1.5;
}

.ts-sec.ts-sec--untitled {
    --ke-sec-gap: 0.5rem;
    display: block;
    padding: 0;
    border: 0;
}

.ts-sec.ts-sec--untitled > .ts-sec__body {
    display: block;
}

/* The band: full-bleed paper by ink overflow on the section, head and lede left, body right. */
:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) {
    --ke-sec-gap: 0.5rem;
    grid-template-columns: minmax(min(18.75rem, 100%), 1fr) minmax(0, 2fr);
    grid-template-rows: auto 1fr;
    grid-template-areas: "head body" "more body";
    gap: 1.125rem 2rem;
    padding-block: var(--ke-band-pad);
    border: 0;
    border-image: linear-gradient(var(--ke-page) 0 0) fill 0 // 0 100vmax;
    background-color: var(--ke-page);
}

:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) > .ts-sec__head {
    align-self: start;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 1.125rem;
    margin: 0;
}

/* Authored content keeps its "more" link in place inside the band body. */
:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) > .ts-sec__body > .mod-custom:has(> .ts-sec__more) {
    display: block;
}

:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) > .ts-sec__body > * {
    grid-area: body;
}

:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) > .ts-sec__body > .ts-sec__more {
    grid-area: more;
    align-self: start;
    margin: 0;
}

:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) .ts-sec__title {
    flex-direction: column;
    align-items: flex-start;
    row-gap: 1.125rem;
    font-size: var(--ke-t-band);
    font-weight: var(--ke-w-display);
    line-height: var(--ke-lh-page);
    letter-spacing: var(--ke-track-page);
}

:is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) .ts-sec__sub {
    max-inline-size: 34ch;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-lede);
    line-height: var(--ke-lh-body);
}

@media (width < 62.5rem) {
    :is(.ke-sec[data-ke-scope="paper"], .ts-row[data-ts-row="band"] .ts-sec) {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: none;
        grid-template-areas: "head" "more" "body";
        row-gap: 1.5rem;
    }
}

/* Module heads: 2px rule, 16px down, mono 13/1.2 600 0.08em caps title, 18px to the content. */
:is(.ts-card, .ts-panel):has(> :is(.ts-card__title, .ts-panel__title)),
.ts-module:not(.ts-card, .ts-panel, .ts-sec):has(> .ts-module__title) {
    display: flex;
    flex-direction: column;
    gap: 1.125rem;
    min-inline-size: 0;
    margin: 0;
    padding-block-start: 1rem;
    border-block-start: 2px solid var(--ke-rule);
}

:is(.ts-card, .ts-panel) {
    min-inline-size: 0;
    margin: 0;
    color: var(--ke-ink);
}

:is(.ts-card__title, .ts-panel__title, .ts-module__title) {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-index);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
    overflow-wrap: anywhere;
}

:is(.ts-card, .ts-panel):has(> :is(.ts-card__body, .ts-panel__body) > :is(.ke-related, .ke-months, .ke-rank, .ke-events, .mod-menu)) {
    gap: 0.375rem;
}

:is(.ts-card__body, .ts-panel__body) {
    min-inline-size: 0;
}

/* A side module's "more" link closes the module (Coming up, What you told us). */
:is(.ts-card__body, .ts-panel__body):has(> .ts-sec__more) {
    display: flex;
    flex-direction: column;
}

:is(.ts-card__body, .ts-panel__body) > .ts-sec__more {
    order: 1;
    margin-block-start: 0.75rem;
}

/* A plain mod_menu in a side module reads as link rows. */
:is(.ts-card__body, .ts-panel__body, .ts-module) > .mod-menu {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

:is(.ts-card__body, .ts-panel__body, .ts-module) > .mod-menu > li {
    margin: 0;
    border-block-end: 1px solid var(--ke-hairline);
}

:is(.ts-card__body, .ts-panel__body, .ts-module) > .mod-menu > li > :is(a, span) {
    display: flex;
    align-items: center;
    min-block-size: var(--ke-control-h);
    padding: 0.625rem 0;
    color: var(--ke-ink);
    font-size: var(--ke-t-body);
    font-weight: 600;
    line-height: 1.35;
    text-decoration: none;
}

:is(.ts-card__body, .ts-panel__body, .ts-module) > .mod-menu > li > a:hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

:is(.ts-card__body, .ts-panel__body, .ts-module) > .mod-menu > :is(.current, .active) > a {
    color: var(--ts-link);
}

/* 12. Table (DESIGN_SPEC 7.12): ruled wrapper that scrolls, mono heads, hairline rows. A table keeps
   640px and the wrapper scrolls below that; kestrel.js 6.7 makes an overflowing wrapper a named,
   focusable region (K56). ---------------------------------------------------------------------- */

.ke-table {
    max-inline-size: 100%;
    overflow-x: auto;
    border-block-start: 2px solid var(--ke-rule);
}

.ke-table > table {
    inline-size: 100%;
    min-inline-size: 40rem;
    margin: 0;
    border-collapse: collapse;
    color: var(--ke-ink);
    font-size: var(--ke-t-ui);
}

.ke-table > table > caption {
    padding: 0.875rem 0 0.25rem;
    color: var(--ke-ink);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-index);
    font-weight: 600;
    letter-spacing: var(--ke-track-eyebrow);
    text-align: start;
    text-transform: uppercase;
    caption-side: top;
}

.ke-table > table > thead > tr > th {
    padding: 0.875rem 1rem 0.875rem 0;
    border-block-end: 1px solid var(--ke-hairline);
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    font-weight: 500;
    letter-spacing: var(--ke-track-eyebrow);
    text-align: start;
    text-transform: uppercase;
    vertical-align: bottom;
}

.ke-table > table > tbody > tr > :is(th, td) {
    padding: 1.125rem 1rem 1.125rem 0;
    border-block-end: 1px solid var(--ke-hairline);
    text-align: start;
    vertical-align: top;
}

/* Row heads at 600 (Article board); a title link alone in the first cell is Bricolage 18/600 ink,
   plain until hover (StyleGuide 07, DESIGN_SPEC 7.12); a date in a time element is mono 13 ink 3.
   (0,2,5) and (0,1,5) so the prose link rule of base.css does not reach them. */
.ke-table > table > tbody > tr > th {
    font-weight: 600;
}

.ke-table > table > tbody > tr > :first-child > a:only-child {
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-row);
    font-weight: 600;
    line-height: 1.35;
    text-decoration: none;
}

.ke-table > table > tbody > tr > :first-child > a:only-child:hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.ke-table > table > tbody > tr > td > time {
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-help);
    letter-spacing: var(--ke-track-meta);
    font-variant-numeric: tabular-nums;
}

/* 13. Avatars (DESIGN_SPEC 7.13): circles, mono initials in the tone ink on the tone ground. ---- */

.ts-avatar {
    position: relative;
    display: inline-grid;
    place-items: center;
    flex: none;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    border-radius: 50%;
    background-color: var(--ke-slate);
    color: var(--ke-slate-ink);
    font-family: var(--ke-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1;
    text-transform: uppercase;
}

.ts-avatar.ts-avatar--tone-1 { background-color: var(--ke-sand); color: var(--ke-sand-ink); }
.ts-avatar.ts-avatar--tone-2 { background-color: var(--ke-sage); color: var(--ke-sage-ink); }
.ts-avatar.ts-avatar--tone-3 { background-color: var(--ke-rose); color: var(--ke-rose-ink); }
.ts-avatar.ts-avatar--tone-4 { background-color: var(--ke-paper); color: var(--ke-ink-2); }
.ts-avatar.ts-avatar--tone-5 { background-color: var(--ts-tint); color: var(--ts-on-tint); }

.ts-avatar.ke-avatar--88 { inline-size: 5.5rem; block-size: 5.5rem; font-size: 1.625rem; }
.ts-avatar.ke-avatar--44 { inline-size: 2.75rem; block-size: 2.75rem; font-size: 0.875rem; }
.ts-avatar.ke-avatar--36 { inline-size: 2.25rem; block-size: 2.25rem; font-size: 0.8125rem; }
.ts-avatar.ke-avatar--28 { inline-size: 1.75rem; block-size: 1.75rem; font-size: 0.625rem; }

.ts-avatar > .ts-avatar__img {
    inline-size: 100%;
    block-size: 100%;
    border-radius: 50%;
    object-fit: cover;
}

.ts-avatar.ts-avatar--online::after {
    content: "";
    position: absolute;
    inset-block-end: 0;
    inset-inline-end: 0;
    inline-size: 0.625rem;
    block-size: 0.625rem;
    border-radius: 50%;
    background-color: var(--ke-success);
    box-shadow: 0 0 0 2px var(--ke-page);
}

/* 14. Image placeholders (DESIGN_SPEC 7.14): the tone ground and one shape, no monogram. -------- */

.ts-postcard__media.ts-postcard__media--placeholder {
    position: relative;
    aspect-ratio: 3 / 2;
    overflow: hidden;
    border-radius: var(--ke-r-img);
    background-color: var(--ke-slate);
}

.ts-postcard__media--placeholder::after {
    content: "";
    position: absolute;
    inset-block-end: 0;
    inset-inline-end: 12%;
    inline-size: 44%;
    block-size: 50%;
    background-color: var(--ke-slate-shape);
}

.ts-postcard__media--placeholder[data-ts-art="1"] { background-color: var(--ke-sand); }
.ts-postcard__media--placeholder[data-ts-art="1"]::after { background-color: var(--ke-sand-shape); }
.ts-postcard__media--placeholder[data-ts-art="2"] { background-color: var(--ke-sage); }
.ts-postcard__media--placeholder[data-ts-art="2"]::after { background-color: var(--ke-sage-shape); }
.ts-postcard__media--placeholder[data-ts-art="3"] { background-color: var(--ke-rose); }
.ts-postcard__media--placeholder[data-ts-art="3"]::after { background-color: var(--ke-rose-shape); }
.ts-postcard__media--placeholder[data-ts-art="4"] { background-color: var(--ke-paper); }
.ts-postcard__media--placeholder[data-ts-art="4"]::after { background-color: var(--ke-hairline); }

.ts-postcard__media--placeholder > .ts-postcard__monogram {
    display: none;
}

/* 15. Date block and event rows (DESIGN_SPEC 7.15, kestrel:events-list). ------------------------- */

.ke-events {
    margin: 0;
    padding: 0;
    list-style: none;
}

.ke-event {
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr);
    gap: 1rem;
    margin: 0;
    padding: 1.25rem 0;
    border-block-end: 1px solid var(--ke-hairline);
}

.ke-event__date {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    inline-size: 4.5rem;
    block-size: 4.5rem;
    border-radius: var(--ke-r);
    background-color: var(--ke-paper);
}

:is(.ke-event__month, .ke-event__weekday) {
    font-family: var(--ke-mono);
    font-size: var(--ke-t-micro);
    line-height: 1.2;
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
}

.ke-event__month {
    color: var(--ts-link);
    font-weight: 600;
}

.ke-event__weekday {
    color: var(--ke-ink-3);
}

.ke-event__day {
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: 1.875rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: var(--ke-track-h2);
}

.ke-event__title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: 1.1875rem;
    font-weight: var(--ke-w-h3);
    line-height: 1.25;
    letter-spacing: var(--ke-track-list);
}

.ke-event__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.75rem;
    margin: 0;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-label);
    line-height: 1.4;
}

/* 16. Facepile (DESIGN_SPEC 7.16): three 28px faces overlapping by 8px, then the count. ---------- */

.ke-event__people {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin: 0;
    color: var(--ke-ink-2);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-help);
    font-variant-numeric: tabular-nums;
}

.ke-facepile {
    display: inline-flex;
    padding-inline-start: 0.5rem;
}

.ke-facepile > .ts-avatar {
    inline-size: 1.75rem;
    block-size: 1.75rem;
    margin-inline-start: -0.5rem;
    border: 2px solid var(--ke-page);
    font-size: 0.625rem;
}

/* 17. Stat tile: the Rewardify app's own screens, skinned in ext/rewardify.css (DV10); no class. */

/* 18. Badge medallions (DESIGN_SPEC 7.18): 64px (48 in lists), wash fill, accent icon 28. -------- */

.ke-medal {
    display: inline-grid;
    place-items: center;
    flex: none;
    inline-size: 4rem;
    block-size: 4rem;
    border: 1px solid var(--ke-accent-line);
    border-radius: 50%;
    background-color: var(--ke-accent-wash);
    color: var(--ke-accent);
}

.ke-medal > svg {
    inline-size: 1.75rem;
    block-size: 1.75rem;
}

.ke-medal.ke-medal--uncommon {
    border: 2px solid var(--ke-accent);
}

.ke-medal.ke-medal--rare {
    margin: 0.3125rem;
    border: 2px solid var(--ke-accent);
    box-shadow: 0 0 0 3px var(--ke-page), 0 0 0 5px var(--ke-accent);
}

.ke-medal.ke-medal--locked {
    border: 1px dashed var(--ke-control);
    background-color: var(--ke-paper);
    color: var(--ke-ink-3);
}

.ke-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ke-badges .ke-medal {
    inline-size: 3rem;
    block-size: 3rem;
}

.ke-badges .ke-medal > svg {
    inline-size: 1.375rem;
    block-size: 1.375rem;
}

/* 19. Feed post (DESIGN_SPEC 7.19, mod_sociable_feed kestrel:studio). ---------------------------- */

.ke-feed {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(21.25rem, 100%), 1fr));
    column-gap: 2.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ke-feed > li {
    margin: 0;
}

.ke-post {
    display: grid;
    grid-template-columns: 2.25rem minmax(0, 1fr);
    gap: 0.875rem;
    padding: 1.375rem 0;
    border-block-end: 1px solid var(--ke-hairline);
}

.ke-post__body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-inline-size: 0;
}

.ke-post__who {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.125rem 0.625rem;
    margin: 0;
    line-height: 1.35;
}

.ke-post__author {
    color: var(--ke-ink);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    text-decoration: none;
}

.ke-post__author:hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

:is(.ke-post__meta, .ke-post__stats) {
    margin: 0;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: 0.02em;
    overflow-wrap: anywhere;
}

.ke-post__stats {
    letter-spacing: var(--ke-track-meta);
}

.ke-post__meta a {
    color: var(--ke-ink-2);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ke-post__text {
    margin: 0;
    color: var(--ke-ink);
    font-size: var(--ke-t-body);
    line-height: var(--ke-lh-intro);
    overflow-wrap: break-word;
}

.ke-post__media {
    display: block;
    inline-size: 100%;
    aspect-ratio: 3 / 2;
    border-radius: var(--ke-r-img);
    object-fit: cover;
}

/* 20. Choice rows and scales: the Community Surveys app, skinned in its section 6 (no class). --- */

/* 21. Progress bar (DESIGN_SPEC 7.21): native progress, 8px pill, accent fill on the hairline. -- */

.ke-progress {
    display: block;
    inline-size: 100%;
    block-size: 0.5rem;
    overflow: hidden;
    border: 0;
    border-radius: var(--ke-pill);
    background-color: var(--ke-hairline);
    color: var(--ke-accent);
    appearance: none;
}

.ke-progress::-webkit-progress-bar {
    border-radius: var(--ke-pill);
    background-color: var(--ke-hairline);
}

.ke-progress::-webkit-progress-value {
    border-radius: var(--ke-pill);
    background-color: var(--ke-accent);
}

.ke-progress::-moz-progress-bar {
    border-radius: var(--ke-pill);
    background-color: var(--ke-accent);
}

/* 22. Share row and the article index (PAGES.md 3.2, 6.2 to 6.4). --------------------------------- */

.ke-share {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 0.625rem;
    margin: 0;
    padding: 1.125rem 0;
    border-block: 1px solid var(--ke-hairline);
}

.ke-share__label {
    margin: 0 0.5rem 0 0;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-eyebrow);
    font-weight: 600;
    line-height: var(--ke-lh-label);
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
}

.ke-share__status {
    color: var(--ke-ink-2);
    font-size: var(--ke-t-label);
}

/* Rendered while empty: the live region exists before its message. */
.ke-share__status:empty {
    position: absolute;
}

.ke-toc {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin: 0;
    padding-block-start: 1rem;
    border-block-start: 2px solid var(--ke-rule);
}

.ke-toc__title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-index);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
}

.ke-toc__list {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ke-toc__list > li {
    margin: 0;
    border-block-end: 1px solid var(--ke-hairline);
}

.ke-toc__list a {
    display: grid;
    grid-template-columns: 2rem minmax(0, 1fr);
    align-items: baseline;
    gap: 0.5rem;
    min-block-size: var(--ke-control-h-sm);
    padding: 0.75rem 0;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-ui);
    font-weight: 500;
    line-height: 1.4;
    text-decoration: none;
}

.ke-toc__list a:hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ke-toc__list a[aria-current="location"] {
    color: var(--ts-link);
    font-weight: 600;
}

.ke-toc__num {
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    font-weight: 500;
    letter-spacing: var(--ke-track-index);
}

.ke-toc__list a[aria-current="location"] > .ke-toc__num {
    color: var(--ts-link);
}

/* The article index before the body (no sidebar, or below the drawer breakpoint). */
.ke-toc:has(+ .ts-article__body) {
    margin-block-end: 2.5rem;
}

/* 23. The error document body (PAGES.md 2.8, Error board). The docbar is in layout.css. --------- */

.ke-error {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 2rem 4rem;
    padding-block: 4.5rem 6rem;
}

.ke-error__code {
    flex: 1 1 27.5rem;
    min-inline-size: 0;
    margin: 0;
    color: var(--ts-link);
    font-family: var(--ke-display);
    font-size: var(--ke-t-code);
    font-weight: var(--ke-w-code);
    line-height: 0.85;
    letter-spacing: var(--ke-track-code);
    font-synthesis-weight: none;
}

.ke-error__main {
    display: flex;
    flex: 999 1 32.5rem;
    flex-direction: column;
    gap: 2.25rem;
    min-inline-size: 0;
}

.ke-error__intro {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.ke-error__title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-page);
    font-weight: var(--ke-w-display);
    line-height: var(--ke-lh-page);
    letter-spacing: var(--ke-track-page);
    font-synthesis-weight: none;
    text-wrap: balance;
    overflow-wrap: break-word;
}

.ke-error__lede {
    max-inline-size: 52ch;
    margin: 0;
    color: var(--ke-ink-2);
    font-size: var(--ke-t-intro);
    line-height: var(--ke-lh-intro);
    text-wrap: pretty;
    overflow-wrap: anywhere;
}

.ke-error__search {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0;
}

.ke-error__row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.ke-error__field {
    position: relative;
    flex: 999 1 16.25rem;
    min-inline-size: 0;
}

.ke-error__field > svg {
    position: absolute;
    inset-block-start: 0.9375rem;
    inset-inline-start: 0.875rem;
    inline-size: 1.125rem;
    block-size: 1.125rem;
    color: var(--ke-ink-3);
    pointer-events: none;
}

.ke-error__field > .ts-input {
    padding-inline-start: 2.625rem;
}

.ke-error__search .ke-btn {
    flex: 1 1 auto;
}

.ke-error__sections {
    display: flex;
    flex-direction: column;
    gap: 1.125rem;
    padding-block-start: 1rem;
    border-block-start: 2px solid var(--ke-rule);
}

.ke-error__sections-title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-index);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ke-track-eyebrow);
    text-transform: uppercase;
}

.ke-error__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.75rem;
}

.ke-error__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 0;
}

.ke-error__details {
    min-inline-size: 0;
}

.ke-error__details[open] {
    flex-basis: 100%;
}

.ke-error__details > summary {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-block-size: var(--ke-control-h-sm);
    color: var(--ke-ink);
    font-size: var(--ke-t-ui);
    font-weight: 600;
    list-style: none;
    cursor: pointer;
}

.ke-error__details > summary::-webkit-details-marker {
    display: none;
}

.ke-error__details > summary::after {
    content: "";
    inline-size: 1rem;
    block-size: 1rem;
    background-color: currentColor;
    -webkit-mask: var(--ke-i-chevron) center / contain no-repeat;
    mask: var(--ke-i-chevron) center / contain no-repeat;
    transition: transform var(--ec-dur-1) var(--ec-ease);
}

.ke-error__details[open] > summary::after {
    transform: rotate(180deg);
}

.ke-error__panel {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-block-start: 0.5rem;
    padding: 1.125rem 1.25rem;
    overflow-x: auto;
    border: 1px solid var(--ke-hairline);
    border-radius: var(--ke-r);
    background-color: var(--ke-paper);
    color: var(--ke-ink-2);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-label);
    line-height: 1.6;
}

.ke-error__panel > p {
    margin: 0;
    overflow-wrap: anywhere;
}

.ke-error__panel > .ke-error__path {
    color: var(--ke-ink);
    font-weight: 600;
}

/* 24. The offline document body (PAGES.md 2.8, Offline board): the band notice and the login card. */

.ke-offline {
    display: flex;
    flex-wrap: wrap;
    min-block-size: 100vh;
    min-block-size: 100svh;
}

.ke-offline__notice {
    display: flex;
    flex: 1 1 32.5rem;
    flex-direction: column;
    justify-content: space-between;
    gap: 3.5rem;
    min-inline-size: 0;
    padding: clamp(2rem, 6vw, 6rem);
    background-color: var(--ke-band);
    color: var(--ke-band-ink);
}

.ke-offline__brand {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    min-block-size: var(--ke-control-h-sm);
    margin: 0;
    color: var(--ke-band-strong);
    font-family: var(--ke-display);
    font-size: var(--ke-t-brand-s);
    font-weight: 700;
    line-height: 1;
    letter-spacing: var(--ke-track-feature);
}

.ke-offline__brand > img {
    block-size: 2.125rem;
    inline-size: auto;
}

.ke-offline__intro {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.ke-offline__notice .ke-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    color: var(--ke-band-ink-3);
}

.ke-offline__notice .ke-eyebrow::before {
    content: "";
    flex: none;
    inline-size: 0.5rem;
    block-size: 0.5rem;
    background-color: var(--ke-accent);
}

.ke-offline__title {
    margin: 0;
    color: var(--ke-band-strong);
    font-family: var(--ke-display);
    font-size: var(--ke-t-offline);
    font-weight: var(--ke-w-display);
    line-height: 0.98;
    letter-spacing: var(--ke-track-display);
    font-synthesis-weight: none;
    text-wrap: balance;
    overflow-wrap: break-word;
}

.ke-offline__message {
    max-inline-size: 40ch;
    color: var(--ke-band-ink-2);
    font-size: var(--ke-t-intro);
    line-height: var(--ke-lh-intro);
    text-wrap: pretty;
}

.ke-offline__message > p {
    margin: 0;
}

.ke-offline__media > img {
    display: block;
    max-inline-size: 100%;
    block-size: auto;
    border-radius: var(--ke-r-img);
}

.ke-offline__foot {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    margin: 0;
    padding-block-start: 1.25rem;
    border-block-start: 1px solid var(--ke-band-line);
    color: var(--ke-band-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    line-height: 1.4;
    letter-spacing: var(--ke-track-meta);
}

.ke-offline__login {
    display: flex;
    flex: 1 1 26.25rem;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    min-inline-size: 0;
    padding: clamp(2rem, 6vw, 6rem);
}

.ke-offline__login > #system-message-container {
    inline-size: 100%;
    max-inline-size: 25rem;
}

.ke-offline__card {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    inline-size: 100%;
    max-inline-size: 25rem;
    padding: clamp(1.5rem, 3vw, 2.25rem);
    border: 1px solid var(--ke-hairline);
    border-radius: var(--ke-r);
    background-color: var(--ke-page);
}

.ke-offline__head {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.ke-offline__card .ke-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.ke-offline__card .ke-eyebrow::before {
    content: "";
    flex: none;
    inline-size: 1rem;
    block-size: 1rem;
    background-color: currentColor;
    -webkit-mask: var(--ke-i-lock) center / contain no-repeat;
    mask: var(--ke-i-lock) center / contain no-repeat;
}

.ke-offline__card-title {
    margin: 0;
    color: var(--ke-ink);
    font-family: var(--ke-display);
    font-size: var(--ke-t-panel);
    font-weight: var(--ke-w-h2);
    line-height: var(--ke-lh-panel);
    letter-spacing: var(--ke-track-h2);
}

.ke-offline__note {
    margin: 0;
    color: var(--ke-ink-3);
    font-size: var(--ke-t-ui);
    line-height: 1.5;
}

/* The kit's form inside the card: the legend repeats the card title, so it stays for screen
   readers only; fields 20px apart; the submit spans the card. */
.ke-offline__card .ts-offline__fieldset {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    min-inline-size: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

.ke-offline__card .ts-offline__legend {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.ke-offline__card :is(.ts-offline__submit, .ts-offline__extra) {
    inline-size: 100%;
}

/* The docfoot under the error document (the full footer needs the engine, PAGES.md 2.8). */
.ke-docfoot {
    padding-block: 1.5rem;
    border-block-start: 1px solid var(--ke-hairline);
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: var(--ke-track-meta);
}

.ke-docfoot__copy {
    margin: 0;
}

/* Reduced motion: state changes stay, movement goes (DESIGN_SPEC 8). */
@media (prefers-reduced-motion: reduce) {
    .ke-error__details > summary::after {
        transition: none;
    }
}

/* 25. Article module layouts (PAGES.md 3.1, 3.2): kestrel:more as the paper band under the article,
   the guides list items, teaser card images and the middle dots of the module meta lines. ------ */

/* Each dot hangs in the column gap before its part; a part that wraps takes its dot past the line
   start, where the line's clip-path cuts it off (as the article meta lines in views.css). */
:is(.ke-card__meta, .ke-guide__meta, .ke-rank__meta) > span + span,
.ts-articles__meta > span + time {
    position: relative;
}

:is(.ke-card__meta, .ke-guide__meta, .ke-rank__meta) > span + span::before,
.ts-articles__meta > span + time::before {
    content: "\00B7" / "";
    position: absolute;
    inset-block-start: 0;
    inset-inline-end: calc(100% + 0.625rem);
    color: var(--ke-ink-3);
}

.ke-morefrom {
    display: flex;
    flex-direction: column;
    padding-block: var(--ke-band-pad);
    border-image: linear-gradient(var(--ke-page) 0 0) fill 0 // 0 100vmax;
    background-color: var(--ke-page);
    color: var(--ke-ink);
}

.ke-morefrom > .ke-head {
    margin-block-end: 2rem;
}

.ke-guides > .ke-guides__item {
    display: flex;
    margin: 0;
}

.ke-guides__item > .ke-guide {
    flex: 1 1 auto;
}

.ke-card__media img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

/* The kit's mod_articles "studio" list (BUILD_BRIEF M3 task 3): the teaser card of DESIGN_SPEC 7
   (eyebrow, title, author and date, excerpt) in an auto-fill grid, one column in a sidebar. */
.ts-articles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
    gap: 2rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ts-articles > .ts-articles__item {
    min-inline-size: 0;
    margin: 0;
}

:is(.ts-articles__article, .ts-articles__body) {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    min-inline-size: 0;
}

.ts-articles__article {
    gap: 0.875rem;
}

.ts-articles__media > figure {
    aspect-ratio: 3 / 2;
    margin: 0;
    overflow: hidden;
    border-radius: var(--ke-r-img);
    background-color: var(--ke-paper);
}

.ts-articles__media img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

.ts-articles__excerpt > p {
    margin: 0;
}

.ts-articles__more {
    margin: 0;
    font-size: var(--ke-t-ui);
    font-weight: 600;
}

.ts-articles__more > a {
    color: var(--ke-ink);
    text-decoration: none;
}

.ts-articles__more > a:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* 26. Generic Bootstrap baseline (BUILD_BRIEF M3 task 5, INTEGRATIONS 9): what a component that
   prints plain Bootstrap 5 markup gets beyond the bridge and the K knobs. Only the names lint R4
   allows; a selector carries one more element or the body prefix where joomla.css (printed later)
   or Bootstrap's pseudo-classes draw the same element. -------------------------------------------- */

:is(label, legend).form-label {
    color: var(--ke-ink);
    font-family: var(--ke-sans);
    font-size: var(--ke-t-label);
    font-weight: 600;
    line-height: var(--ke-lh-label);
}

:is(.form-control, .form-select)::placeholder {
    color: var(--ke-ink-3);
    opacity: 1;
}

body :is(.form-control, .form-select):focus {
    border-color: var(--ke-accent);
    box-shadow: 0 0 0 var(--ke-halo-w) var(--ke-accent-halo);
}

body :is(.form-control, .form-select):is(.is-invalid, [aria-invalid="true"]) {
    border-color: var(--ke-danger);
}

body :is(.form-control, .form-select):is(.is-invalid, [aria-invalid="true"]):focus {
    box-shadow: 0 0 0 var(--ke-halo-w) var(--ke-danger-soft);
}

div.invalid-feedback {
    color: var(--ke-danger);
    font-size: var(--ke-t-help);
    line-height: var(--ke-lh-help);
}

.alert > .alert-heading {
    margin: 0 0 0.25rem;
    color: inherit;
    font-family: var(--ke-display);
    font-size: var(--ke-t-row);
    font-weight: var(--ke-w-h3);
    line-height: 1.3;
}

.nav-pills {
    --bs-nav-link-color: var(--ke-ink);
    --bs-nav-link-hover-color: var(--ke-ink);
    --bs-nav-pills-border-radius: var(--ke-pill);
    --bs-nav-pills-link-active-bg: var(--ke-ink);
    --bs-nav-pills-link-active-color: var(--ke-on-ink);
    gap: 0.5rem;
}

.breadcrumb {
    --bs-breadcrumb-divider-color: var(--ke-ink-3);
    --bs-breadcrumb-item-active-color: var(--ke-ink);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: var(--ke-track-meta);
}

.breadcrumb > .breadcrumb-item > a {
    color: var(--ke-ink-2);
    text-decoration: none;
}

.breadcrumb > .breadcrumb-item > a:hover {
    color: var(--ke-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Core and third-party info blocks as one mono meta line; Joomla's icons stay out of the line. */
dl.article-info {
    --bs-secondary-color: var(--ke-ink-3); /* core's .text-muted */
    gap: 0.25rem 1.25rem;
    color: var(--ke-ink-3);
    font-family: var(--ke-mono);
    font-size: var(--ke-t-meta);
    letter-spacing: var(--ke-track-meta);
}

dl.article-info > dd > :is([class^="icon-"], [class*=" icon-"]) {
    display: none;
}

dl.article-info a {
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}
