/*-----------------------------------------------------------------------------
 * Project : MaterielAV - CFP Arts
 * File    : public/assets/css/app.css
 * Style   : Main application stylesheet
 * Author  : Johann Sievering
 * AI Support : Claude AI
 * Date    : 2026-04-06 Start of the project
 * Rev     : 2026-08-25 Users tab bar search state (.user-tabs--searching)
 * Version : 0.9.0
 *-----------------------------------------------------------------------------
 * Main application stylesheet (plain CSS, no framework): design tokens,
 * layout chrome (header, footer, mobile bottom navigation), forms, badges,
 * the DataTable component, page-specific blocks and the responsive rules
 * (page zoom, shutters, bottom sheets).
 *---------------------------------------------------------------------------*/
/*
 * MaterielAV — base stylesheet.
 *
 * Plain CSS, no framework. Defines a small set of design tokens (custom
 * properties), a fixed header/footer layout, and the styling used by the
 * Milestone 1 diagnostic page. Kept intentionally simple and responsive.
 */

:root {
    --color-bg: #f5f6f8;
    --color-surface: #ffffff;
    --color-text: #1f2733;
    --color-muted: #5b6573;
    --color-border: #e2e6eb;
    --color-primary: #2c6e8f;
    --color-ok-bg: #e4f4ea;
    --color-ok-text: #1d7a45;
    --color-error-bg: #fbe4e4;
    --color-error-text: #b3261e;
    /* Themeable interface colors (overridable from Paramètres). */
    --header-bg: #2c6e8f;
    --header-text: #ffffff;
    --footer-bg: #ffffff;
    --footer-text: #5b6573;
    --header-height: 56px;
    --footer-height: 44px;
    --radius: 8px;
    --max-width: 960px;
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    color: var(--color-text);
    background-color: var(--color-bg);
    line-height: 1.5;
    /* The window never scrolls: content scrolls inside .app-main instead. */
    overflow: hidden;
}

/* --- Fixed header --- */
.app-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--header-height);
    display: flex;
    align-items: center;
    padding: 0 1.25rem 0 0;
    background-color: var(--header-bg);
    color: var(--header-text);
    z-index: 10;
}

.app-header__brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--header-text);
    text-decoration: none;
    font-weight: 600;
    font-size: 1.1rem;
}

.app-header__logo {
    /* "Native" header look: the (transparent) logo art is recoloured to solid
       white with a filter and sits directly on the header — no backing box. This
       suits a monochrome mark; a colored uploaded logo would be whitened too. */
    height: 38px;
    width: auto;
    max-width: 200px;
    display: block;
    margin: 0;
    padding: 0;
    filter: brightness(0) invert(1);
    object-fit: contain;
}

.app-header__brand-text {
    white-space: nowrap;
}

/* --- Main content: the only vertical scroll container (window never scrolls) --- */
.app-main {
    position: fixed;
    top: var(--header-height);
    bottom: var(--footer-height);
    left: 0;
    right: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 1.5rem 1.25rem;
}

.app-main__inner {
    max-width: var(--max-width);
    margin: 0 auto;
}

/* Full-width data-table pages use the whole width, with tight bottom spacing so
   the table sits close to the footer. The DataTable's exact height is set by JS
   (fitWideTables) so its body scrolls and its footer stays pinned just above the
   page footer. */
.app-main--wide .app-main__inner {
    max-width: none;
}

.app-main--wide {
    padding-bottom: 0.6rem;
}

.app-main--wide .shutter {
    margin-bottom: 0.6rem;
}

/* --- Fixed footer --- */
.app-footer {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--footer-height);
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--footer-bg);
    border-top: 1px solid var(--color-border);
    color: var(--footer-text);
    font-size: 0.85rem;
}

.app-footer__text {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.app-footer__sep {
    opacity: 0.5;
}

.app-footer__link {
    color: inherit;
    text-decoration: none;
    font-weight: 600;
}

.app-footer__link:hover {
    text-decoration: underline;
}

.app-footer__env {
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #8a5a12;
    background: #fdf1d6;
    border: 1px solid #f0d49a;
}

/* --- Diagnostic page --- */
.diagnostic__title {
    margin-top: 0;
}

.diagnostic__summary {
    padding: 0.75rem 1rem;
    border-radius: var(--radius);
    font-weight: 500;
}

.diagnostic__summary--ok {
    background-color: var(--color-ok-bg);
    color: var(--color-ok-text);
}

.diagnostic__summary--error {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
}

.diagnostic__table {
    width: 100%;
    margin-top: 1.5rem;
    border-collapse: collapse;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
}

.diagnostic__table th,
.diagnostic__table td {
    text-align: left;
    padding: 0.7rem 0.9rem;
    border-bottom: 1px solid var(--color-border);
    vertical-align: top;
}

.diagnostic__table thead th {
    background-color: #eef1f4;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-muted);
}

.diagnostic__table tr:last-child td {
    border-bottom: none;
}

.diagnostic__detail {
    color: var(--color-muted);
}

/* --- Status badge --- */
.badge {
    display: inline-block;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
}

.badge--ok {
    background-color: var(--color-ok-bg);
    color: var(--color-ok-text);
}

.badge--error {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
}

/* --- Error page --- */
.error-page {
    text-align: center;
    padding-top: 2rem;
}

.error-page__code {
    font-size: 3.5rem;
    margin: 0;
    color: var(--color-primary);
}

.error-page__link {
    color: var(--color-primary);
}

/* --- Header user area --- */
.app-header__user {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

/* Logged-out header: the public "A propos" link, top-right. */
.app-header__guest {
    margin-left: auto;
    display: flex;
    align-items: center;
}

.app-header__username {
    color: var(--header-text);
    font-size: 0.9rem;
    opacity: 0.95;
}

.app-header__role {
    color: var(--header-text);
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.18);
    white-space: nowrap;
}

/* Round account avatar + its dropdown menu */
.app-header__account-menu {
    position: relative;
    display: flex;
    align-items: center;
}

.app-header__avatar-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
}

.app-header__avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    color: var(--color-primary);
    font-size: 0.8rem;
    font-weight: 700;
    border: 2px solid rgba(255, 255, 255, 0.65);
    box-sizing: border-box;
}

.app-header__avatar-btn:hover .app-header__avatar,
.app-header__account-menu.is-open .app-header__avatar {
    border-color: #fff;
}

.app-header__account-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 210px;
    padding: 6px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(31, 39, 51, 0.18);
    display: none;
    flex-direction: column;
    gap: 2px;
    z-index: 20;
}

.app-header__account-menu.is-open .app-header__account-panel {
    display: flex;
}

.app-header__account-head {
    padding: 0.5rem 0.7rem 0.6rem;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 4px;
}

.app-header__account-name {
    display: block;
    font-weight: 600;
    color: var(--color-text);
    font-size: 0.92rem;
}

.app-header__account-role {
    display: block;
    color: var(--color-muted);
    font-size: 0.8rem;
}

.app-header__logout-item {
    margin: 0;
}

.app-header__account-link {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.5rem 0.7rem;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--color-text);
    font-size: 0.9rem;
    font-family: inherit;
    cursor: pointer;
    text-decoration: none;
}

.app-header__account-link:hover {
    background: var(--color-bg);
}

.app-header__logout {
    margin: 0;
}

/* --- Buttons --- */
.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
}

.btn:disabled,
.btn[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn--primary {
    background-color: var(--color-primary);
    color: #fff;
}

.btn--primary:hover {
    background-color: #245a75;
}

/* The login form's submit button spans the full width. */
.login__form .btn--primary {
    width: 100%;
}

.btn--secondary {
    background-color: #eef1f4;
    color: var(--color-text);
    border-color: var(--color-border);
}

.btn--secondary:hover {
    background-color: #e2e6eb;
}

.btn--danger {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
    border-color: #f3c6c3;
}

.btn--danger:hover {
    background-color: #f7d3d1;
}

.btn--ghost-dark {
    background-color: transparent;
    color: var(--color-muted);
    border-color: var(--color-border);
}

.btn--ghost-dark:hover {
    background-color: #eef1f4;
}

.btn--ghost {
    background-color: transparent;
    color: #fff;
    border-color: rgba(255, 255, 255, 0.6);
    padding: 0.3rem 0.7rem;
    font-size: 0.85rem;
}

.btn--ghost:hover {
    background-color: rgba(255, 255, 255, 0.15);
}

/* --- Login --- */
.login {
    max-width: 380px;
    margin: 2rem auto 0;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1.75rem;
}

.login__title {
    margin-top: 0;
    text-align: center;
}

.login__error {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius);
    font-size: 0.9rem;
}

.login__notice {
    background-color: #fdf6ea;
    color: #8a5a12;
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius);
    font-size: 0.9rem;
}

.password-rules {
    font-size: 0.8rem;
    color: var(--color-muted);
}

.password-rules ul {
    margin: 0.25rem 0 0;
    padding-left: 1.1rem;
}

.app-header__account {
    color: #fff;
    text-decoration: none;
    font-size: 0.85rem;
    opacity: 0.9;
}

.app-header__account:hover {
    text-decoration: underline;
    opacity: 1;
}

.login__form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* --- Form fields --- */
.form-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.form-field__label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-muted);
}

.form-field__input {
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font-size: 1rem;
}

.form-field__input:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(44, 110, 143, 0.15);
}

/* Password reveal: an eye button sits to the right of the field. The wrapper is
   injected by core/forms/PasswordToggle.js, so the markup degrades to a plain
   password input when JavaScript is off. */
.password-field {
    position: relative;
    display: block;
}

.password-field .form-field__input {
    width: 100%;
    /* Room for the eye button so the value never runs under it. */
    padding-right: 2.6rem;
}

.password-toggle {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--color-muted);
    cursor: pointer;
    border-radius: var(--radius);
}

.password-toggle:hover {
    color: var(--color-text);
}

.password-toggle:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
}

.password-toggle .icon {
    width: 1.2rem;
    height: 1.2rem;
    vertical-align: 0;
}

/* --- Home / dashboard --- */
.home__lead {
    margin: 0;
    align-self: center;
    text-align: right;
    color: var(--color-muted);
}

.quick-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin: 0.5rem 0 1.25rem;
}

.stat-grid {
    display: grid;
    /* The number of columns is set per page via --stat-cols (= ceil(N/2)), so
       the cards split into balanced rows — equal rows for an even count, one
       extra on the first row for an odd count — and the 1fr columns make the
       grid fill the full content width (same as the shutters below). */
    grid-template-columns: repeat(var(--stat-cols, 3), minmax(0, 1fr));
    gap: 0.9rem;
    margin-bottom: 1.5rem;
}

.stat-card {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--color-border);
    border-left: 4px solid var(--color-border);
    border-radius: var(--radius);
    background-color: var(--color-surface);
    text-decoration: none;
    color: var(--color-text);
    transition: box-shadow 0.12s ease;
}

.stat-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.07);
}

.stat-card__value {
    font-size: 1.8rem;
    font-weight: 700;
    line-height: 1;
}

.stat-card__label {
    font-size: 0.85rem;
    color: var(--color-muted);
}

.stat-card--available {
    border-left-color: var(--color-ok-text);
}

.stat-card--borrowed {
    border-left-color: #2c6e8f;
}

.stat-card--repair {
    border-left-color: #8a5a12;
}

.stat-card--missing,
.stat-card--overdue {
    border-left-color: var(--color-error-text);
}

.stat-card--active {
    border-left-color: var(--color-primary);
}

.home__subtitle {
    font-size: 1rem;
}

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

.tag {
    background-color: #eef1f4;
    color: var(--color-text);
    padding: 0.25rem 0.7rem;
    border-radius: 999px;
    font-size: 0.85rem;
}

/* --- Primary navigation --- */
.app-nav {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: 1.5rem;
}

/* Subtle white divider between the brand (logo + title) and the menu. */
.app-nav::before {
    content: "";
    flex: none;
    align-self: center;
    width: 1px;
    height: 26px;
    margin: 0 1rem 0 0;
    background: rgba(255, 255, 255, 0.4);
}

.app-nav__link {
    color: var(--header-text);
    text-decoration: none;
    font-size: 0.9rem;
    padding: 0.3rem 0.6rem;
    border-radius: var(--radius);
    opacity: 0.9;
}

.app-nav__link:hover {
    background-color: rgba(255, 255, 255, 0.15);
    opacity: 1;
}

.app-nav__link.is-active {
    background-color: rgba(255, 255, 255, 0.22);
    opacity: 1;
}

/* Overflow "…" (kebab) menu */
.app-nav__more {
    position: relative;
    display: flex;
    align-items: center;
}

.app-nav__more-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--header-text);
    cursor: pointer;
    opacity: 0.9;
}

.app-nav__more-btn:hover,
.app-nav__more.is-open .app-nav__more-btn {
    background-color: rgba(255, 255, 255, 0.18);
    opacity: 1;
}

.app-nav__more-icon {
    width: 20px;
    height: 20px;
    fill: currentColor;
}

.app-nav__menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 190px;
    padding: 6px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(31, 39, 51, 0.18);
    display: none;
    flex-direction: column;
    gap: 2px;
    z-index: 20;
}

.app-nav__more.is-open .app-nav__menu {
    display: flex;
}

.app-nav__menu-link {
    display: block;
    padding: 0.5rem 0.7rem;
    border-radius: 6px;
    color: var(--color-text);
    text-decoration: none;
    font-size: 0.9rem;
    white-space: nowrap;
}

.app-nav__menu-link:hover {
    background-color: var(--color-bg);
}

.app-nav__menu-link.is-active {
    color: var(--color-primary);
    font-weight: 600;
}

/* --- Page header --- */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.page-header__title {
    margin: 0.25rem 0 0;
}

.page-header__actions {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.export-form {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.back-link {
    color: var(--color-muted);
    text-decoration: none;
    font-size: 0.85rem;
}

.back-link:hover {
    color: var(--color-primary);
}

.inline-form {
    margin: 0;
    display: inline;
}

/* --- Status badges --- */
.badge--available {
    background-color: var(--color-ok-bg);
    color: var(--color-ok-text);
}

.badge--borrowed {
    background-color: #e4ecf6;
    color: #25557f;
}

.badge--under_repair {
    background-color: #fdf0dc;
    color: #8a5a12;
}

.badge--missing {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
}

.badge--archived {
    background-color: #ebedf0;
    color: #5b6573;
}

/* --- DataTable --- */
.datatable-mount__loading,
.datatable-mount__error {
    color: var(--color-muted);
}

.dt {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    /* Fill the available height so the body scrolls while the header (sticky)
       and the footer stay visible. */
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - var(--header-height) - var(--footer-height) - 7rem);
    overflow: hidden;
}

.dt__toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem;
    border-bottom: 1px solid var(--color-border);
    flex-wrap: wrap;
}

.dt__search {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.dt__search-input {
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    min-width: 220px;
}

.dt__regex {
    font-size: 0.85rem;
    color: var(--color-muted);
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.dt__help {
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    border: 1px solid var(--color-border);
    background-color: #eef1f4;
    cursor: pointer;
    font-weight: 700;
    color: var(--color-primary);
}

.dt__columns {
    position: relative;
}

.dt__columns-btn {
    padding: 0.45rem 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: #fff;
    cursor: pointer;
}

.dt__columns-menu {
    position: absolute;
    right: 0;
    top: 110%;
    background-color: #fff;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
    padding: 0.5rem;
    z-index: 5;
    min-width: 180px;
}

.dt__columns-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.2rem 0.3rem;
    font-size: 0.9rem;
}

.dt__columns-toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
}

.dt__columns-order {
    display: inline-flex;
    gap: 0.15rem;
    flex: 0 0 auto;
}

.dt__columns-move {
    border: 1px solid var(--color-border);
    border-radius: 4px;
    background-color: #fff;
    cursor: pointer;
    line-height: 1;
    /* Comfortable touch target. */
    min-width: 1.8rem;
    padding: 0.25rem 0;
    font-size: 0.7rem;
    color: var(--color-muted);
}

.dt__columns-move:hover:not(:disabled) {
    background-color: #eef4fb;
    color: var(--color-text);
}

.dt__columns-move:disabled {
    opacity: 0.35;
    cursor: default;
}

.dt__search-error {
    padding: 0.5rem 0.75rem;
    color: var(--color-error-text);
    background-color: var(--color-error-bg);
    font-size: 0.85rem;
}

.dt__toolbar,
.dt__footer,
.dt__search-error {
    flex: 0 0 auto;
}

/* Scrollable records area: vertical scrollbar on the right, horizontal when
   needed. The sticky header stays at the top of this container. */
.dt__table-wrap {
    overflow: auto;
    flex: 1 1 auto;
}

.dt__table {
    width: 100%;
    border-collapse: collapse;
}

.dt__table th,
.dt__table td {
    text-align: left;
    padding: var(--dt-cell-pad, 0.55rem 0.75rem);
    border-bottom: 1px solid var(--color-border);
    font-size: var(--dt-font-size, 0.9rem);
    white-space: nowrap;
}

/* Cells may wrap so the table fits the available window width. */
.dt__table td {
    white-space: normal;
}

.dt__table thead th {
    background-color: #f4f6f8;
    font-size: calc(var(--dt-font-size, 0.9rem) * 0.88);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-muted);
    /* Keep the header visible while the records scroll. */
    position: sticky;
    top: 0;
    z-index: 2;
    box-shadow: inset 0 -1px 0 var(--color-border);
}

.dt__th--sortable {
    cursor: pointer;
    user-select: none;
}

.dt__th--asc::after {
    content: ' ▲';
    font-size: 0.7em;
}

.dt__th--desc::after {
    content: ' ▼';
    font-size: 0.7em;
}

/* Per-column filter row (second header row), sticky just under the header. */
.dt__table thead .dt__filter-row th {
    position: sticky;
    top: 34px;
    z-index: 2;
    background-color: #fff;
    padding: 0.3rem 0.5rem;
    text-transform: none;
    letter-spacing: normal;
    box-shadow: inset 0 -1px 0 var(--color-border);
}

/* Active-filter state: amber header signals the table is showing a subset only.
   Applied by DataTable (.dt__table--filtered) and the server-rendered tables
   (.js-table-filter--filtered) whenever a filter is hiding rows. */
.dt__table--filtered thead th,
.js-table-filter--filtered thead th {
    background-color: #ffe7b3;
    color: #7a4f00;
    box-shadow: inset 0 -2px 0 #e0a229;
}

.dt__table--filtered thead .dt__filter-row th {
    background-color: #fff4dd;
    box-shadow: inset 0 -1px 0 #e0a229;
}

.dt__col-filter {
    width: 100%;
    min-width: 4.5rem;
    box-sizing: border-box;
    padding: 0.25rem 0.4rem;
    font-size: 0.8rem;
    border: 1px solid var(--color-border);
    border-radius: 4px;
}

.dt__clear {
    padding: 0.45rem 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: #fff;
    cursor: pointer;
}

.dt__clear:hover {
    background-color: #f4f6f8;
}

.dt__toolbar-right {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.dt__all-warning {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-right: 0.5rem;
}

/* Explicit display above would override the hidden attribute, so re-hide it. */
.dt__all-warning[hidden] {
    display: none;
}

.dt__all-warning-text {
    font-size: 0.75rem;
    color: #8a5a12;
}

.dt__all-confirm {
    padding: 0.2rem 0.5rem;
    font-size: 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    background-color: #fdf6ea;
    color: #8a5a12;
    cursor: pointer;
}

.dt__all-confirm:hover {
    background-color: #f8edd6;
}

/* --- TableFilter (decorates server-rendered tables) --- */
.tablefilter {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.6rem;
    flex-wrap: wrap;
}

.tablefilter__search {
    flex: 1 1 12rem;
    min-width: 8rem;
    padding: 0.45rem 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

.tablefilter__clear {
    padding: 0.45rem 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: #fff;
    cursor: pointer;
}

.tablefilter__clear:hover {
    background-color: #f4f6f8;
}

.tablefilter__row th {
    background-color: #fff;
    padding: 0.3rem 0.5rem;
    text-transform: none;
    letter-spacing: normal;
}

.tablefilter__col {
    width: 100%;
    min-width: 4.5rem;
    box-sizing: border-box;
    padding: 0.25rem 0.4rem;
    font-size: 0.8rem;
    border: 1px solid var(--color-border);
    border-radius: 4px;
}

/* --- Searchable select (enhanced long dropdowns) --- */
.searchselect {
    position: relative;
}

.searchselect__native {
    display: none;
}

.searchselect__panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 20;
    margin: 0.15rem 0 0;
    padding: 0;
    list-style: none;
    max-height: 240px;
    overflow: auto;
    background-color: #fff;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
}

.searchselect__option {
    padding: 0.4rem 0.6rem;
    cursor: pointer;
    font-size: 0.9rem;
}

.searchselect__option:hover,
.searchselect__option.is-selected {
    background-color: #eef4fb;
}

.searchselect__empty {
    padding: 0.4rem 0.6rem;
    color: var(--color-muted);
    font-size: 0.85rem;
}

/* --- Autocomplete dropdown for table column "Filtrer" inputs --- */
/* position: fixed so it is not clipped by the table wrapper's overflow; the
   element is glued under its input by FilterSuggest.js. ~10 rows then scroll. */
.filter-suggest {
    position: fixed;
    z-index: 60;
    margin: 0.1rem 0 0;
    padding: 0;
    list-style: none;
    max-height: calc(2.1rem * 10);
    overflow-y: auto;
    background-color: #fff;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
}

.filter-suggest__option {
    padding: 0.35rem 0.55rem;
    cursor: pointer;
    font-size: 0.8rem;
    white-space: nowrap;
}

.filter-suggest__option:hover,
.filter-suggest__option.is-active {
    background-color: #eef4fb;
}

/* The predefined "Vide" entry: italic, set off from the real values below it. */
.filter-suggest__option--empty {
    font-style: italic;
    color: var(--color-muted);
    border-bottom: 1px solid var(--color-border);
}

/* --- Collapsible "shutter" sections --- */
.shutter {
    margin: 0 0 1.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: var(--color-surface);
    overflow: hidden;
}

/* While a field inside is focused (e.g. the searchable-select dropdown is
   open), the shutter must not clip the absolutely-positioned panel. */
.shutter:focus-within {
    overflow: visible;
}

.shutter__title {
    /* The bar itself is not clickable; only the title + arrow toggle it. */
    cursor: default;
    list-style: none;
    padding: 0.8rem 1rem;
    font-weight: 600;
    font-size: 1rem;
    background-color: #f4f6f8;
    display: flex;
    align-items: center;
    user-select: none;
}

.shutter__title::-webkit-details-marker {
    display: none;
}

/* The clickable toggle: arrow + title text, sized to its content so the rest
   of the bar stays inert. */
.shutter__label {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    cursor: pointer;
}

.shutter__label::before {
    content: '▸';
    color: var(--color-muted);
    font-size: 1.8rem;
    line-height: 1;
    transition: transform 0.15s ease;
}

.shutter[open] > .shutter__title .shutter__label::before {
    transform: rotate(90deg);
}

.shutter__body {
    padding: 1rem;
}


.dt__row--clickable {
    cursor: pointer;
}

.dt__row--clickable:hover td {
    background-color: #f7f9fb;
}

.dt__empty {
    padding: 2rem;
    text-align: center;
    color: var(--color-muted);
}

.dt__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 0.8rem;
    border-top: 1px solid var(--color-border);
    flex-wrap: wrap;
    background-color: var(--color-surface);
}

.dt__count {
    color: var(--color-muted);
    font-size: 0.85rem;
}

.dt__pager {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--color-muted);
}

.dt__page-btn {
    width: 1.9rem;
    height: 1.9rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: #fff;
    cursor: pointer;
}

.dt__page-btn:disabled {
    opacity: 0.4;
    cursor: default;
}

/* --- DataTable RegEx help modal --- */
.dt-modal {
    position: fixed;
    inset: 0;
    background-color: rgba(31, 39, 51, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 50;
}

.dt-modal__dialog {
    background-color: #fff;
    border-radius: var(--radius);
    padding: 1.5rem;
    max-width: 520px;
    width: 100%;
}

.dt-modal__examples {
    margin: 0.5rem 0 1rem;
    padding-left: 1rem;
    line-height: 1.8;
}

.dt-modal__examples code {
    background-color: #eef1f4;
    padding: 0.1rem 0.4rem;
    border-radius: 4px;
    font-size: 0.9em;
}

.dt-modal__hint {
    font-size: 0.85rem;
    color: var(--color-muted);
}

/* --- Material detail sheet --- */
.material-sheet {
    display: grid;
    /* minmax(0, …): a bare 1fr cannot shrink below its content's min-content
       width, so one long unbreakable value (e.g. a URL in the notes) would
       push the fixed photo column off-screen. */
    grid-template-columns: minmax(0, 1fr) 280px;
    gap: 1.5rem;
    align-items: start;
}

.material-sheet__main {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1.25rem;
}

.detail-list {
    display: grid;
    grid-template-columns: 160px minmax(0, 1fr);
    gap: 0.5rem 1rem;
    margin: 0;
}

.detail-list dt {
    color: var(--color-muted);
    font-size: 0.85rem;
}

.detail-list dd {
    margin: 0;
    /* anywhere (not break-word): only "anywhere" lowers the min-content
       width, which is what the grid tracks above size against. */
    overflow-wrap: anywhere;
}

.material-photo {
    width: 100%;
    border-radius: var(--radius);
    border: 1px solid var(--color-border);
    display: block;
}

.material-photo--empty {
    aspect-ratio: 4 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-muted);
    background-color: #f4f6f8;
    font-size: 0.9rem;
}

.photo-form {
    margin-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

/* --- Material form --- */
.material-form {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1.25rem;
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}

.form-field--wide {
    grid-column: 1 / -1;
}

.form-error {
    color: var(--color-error-text);
    font-size: 0.8rem;
    margin: 0.1rem 0 0;
}

.form-error--global {
    background-color: var(--color-error-bg);
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius);
    margin-bottom: 1rem;
}

.form-success {
    background-color: var(--row-borrowed, #e7f5ec);
    border: 1px solid var(--color-primary);
    color: var(--color-text);
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius);
    margin-bottom: 1rem;
    font-weight: 600;
}

/* Contact inbox (admin) */
.message-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 820px;
}

.message-card {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.8rem 1rem;
}

.message-card--unread {
    border-left: 4px solid var(--color-primary);
    background: #f0f6ff;
}

.message-card__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
}

.message-card__subject {
    font-weight: 700;
}

.message-card__date {
    color: var(--color-muted);
    font-size: 0.85rem;
    white-space: nowrap;
}

.message-card__meta {
    margin: 0.25rem 0;
    font-size: 0.9rem;
}

.message-card__body {
    margin: 0.5rem 0 0.75rem;
    white-space: pre-wrap;
}

.message-unread-tag {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0 0.45rem;
    border-radius: 999px;
    background: var(--color-primary);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    vertical-align: middle;
}

/* Unread message rows in the inbox table. */
.dt__row--unread td {
    font-weight: 600;
    background-color: #f0f6ff;
}

/* Triage-status badges (contact messages). */
.msg-status {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 700;
    white-space: nowrap;
}

.msg-status--nouveau {
    background: #1450d6;
    color: #fff;
}

.msg-status--lu {
    background: #e5e7eb;
    color: #374151;
}

.msg-status--en_cours {
    background: #fde9c8;
    color: #92400e;
}

.msg-status--repondu {
    background: #dcfce7;
    color: #166534;
}

.msg-status--clos {
    background: #374151;
    color: #fff;
}

.msg-status--envoi_direct {
    background: #6d28d9;
    color: #fff;
}

/* A reply nested under a message in the per-user conversation thread. */
.message-reply {
    margin: 0.5rem 0 0 1rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--color-border);
}

/* Log-level badges (Journaux). */
.log-level {
    display: inline-block;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
}

.log-level--info,
.log-level--notice {
    background: #e0edff;
    color: #1e40af;
}

.log-level--debug {
    background: #e5e7eb;
    color: #374151;
}

.log-level--warning {
    background: #fef3c7;
    color: #92400e;
}

.log-level--error,
.log-level--critical {
    background: #fee2e2;
    color: #991b1b;
}

/* Pretty-printed context JSON on a log detail page. */
.log-context {
    background: #0f172a;
    color: #e2e8f0;
    padding: 0.8rem 1rem;
    border-radius: var(--radius);
    overflow: auto;
    max-height: 480px;
    font-size: 0.8rem;
    line-height: 1.5;
    white-space: pre;
}


.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

/* --- Checkboxes (roles, active flag) --- */
.checkbox-field {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
}

.roles-field {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
    margin: 0;
}

.roles-field legend {
    padding: 0 0.4rem;
}

.checkbox-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 0.5rem;
    margin-top: 0.5rem;
}

/* Long checkbox lists (e.g. responsible teachers): cap the height and scroll.
   Only the no-JS fallback — TokenSelect.js hides the list behind its widget. */
.checkbox-list--scroll {
    max-height: 14rem;
    overflow-y: auto;
    padding-right: 0.25rem;
}

/* --- TokenSelect (Moodle-style multi-select: search + chips) --- */
.tokenselect {
    margin-top: 0.5rem;
}

.tokenselect__chips {
    margin-top: 0.5rem;
}

.tokenselect__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.tokenselect__remove {
    border: none;
    background: none;
    padding: 0 0.1rem;
    font-size: 1rem;
    line-height: 1;
    color: var(--color-muted);
    cursor: pointer;
}

.tokenselect__remove:hover {
    color: var(--color-text);
}

/* --- Loan status badges --- */
.badge--open {
    background-color: #e4ecf6;
    color: #25557f;
}

.badge--partially_returned {
    background-color: #fdf0dc;
    color: #8a5a12;
}

.badge--returned {
    background-color: var(--color-ok-bg);
    color: var(--color-ok-text);
}

.badge--cancelled {
    background-color: #ebedf0;
    color: #5b6573;
}

.badge--overdue {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
}

/* --- Loans --- */
.section-title {
    margin: 1.5rem 0 0.75rem;
    font-size: 1.1rem;
}

.form-hint {
    color: var(--color-muted);
    font-size: 0.85rem;
    margin-top: 0.5rem;
}

.muted {
    color: var(--color-muted);
}

.history-trigger {
    margin-top: 1.5rem;
}

/* --- Scanner page --- */
.scanner {
    max-width: 640px;
}

.scanner__back {
    display: inline-block;
    margin-bottom: 0.75rem;
}

.scanner__section {
    margin: 0 0 1.25rem;
    padding: 0 0 1.25rem;
    border-bottom: 1px solid var(--color-border);
}

.scanner__section:last-of-type {
    border-bottom: 0;
    margin-bottom: 0;
    padding-bottom: 0;
}

.scanner__section-title {
    margin: 0 0 0.35rem;
    font-size: 1rem;
    font-weight: 600;
}

.scanner__hid {
    width: 100%;
    max-width: 360px;
}

.scanner__manual {
    display: flex;
    gap: 0.5rem;
    margin: 0.75rem 0;
}

.scanner__manual #scanner-input {
    flex: 1;
}

.scanner__camera {
    margin: 0.75rem 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
}

.scanner__video {
    width: 100%;
    max-width: 480px;
    border-radius: var(--radius);
    background-color: #000;
}

.scanner__status {
    color: var(--color-muted);
    font-size: 0.9rem;
    min-height: 1.2em;
}

.scanner__result {
    margin-top: 1rem;
}

.scanner__card {
    display: flex;
    gap: 1rem;
    align-items: center;
    padding: 1rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: var(--color-surface);
}

.scanner__photo {
    width: 96px;
    height: 96px;
    object-fit: cover;
    border-radius: var(--radius);
}

.scanner__card-body {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.scanner__name {
    margin: 0;
    font-size: 1.1rem;
}

.scanner__meta {
    margin: 0;
    color: var(--color-muted);
}

.scanner__none {
    color: var(--color-error-text);
}

/* Clickable rows in history / loan-item tables. */
.dt__table tr.clickable-row {
    cursor: pointer;
}

/* Action buttons inside a table cell. */
.dt-actions {
    white-space: nowrap;
}

.dt-actions .btn + .btn {
    margin-left: 0.3rem;
}

/* Inline SVG icons (stroke-based, inherit the current text color). */
.icon-sprite {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.icon {
    width: 1.05em;
    height: 1.05em;
    vertical-align: -0.15em;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.btn--icon {
    padding: 0.3rem 0.5rem;
    line-height: 1;
}

/* Row "Actions" column: small icon-link buttons with a native tooltip. */
.dt-actions {
    display: inline-flex;
    gap: 0.25rem;
    align-items: center;
}

.dt-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background-color: #fff;
    color: var(--color-muted);
    text-decoration: none;
    font-size: 0.95rem;
}

.dt-action:hover {
    background-color: #eef4fb;
    border-color: #b9d4ef;
    color: var(--color-primary, #1d6fb8);
}

/* Inactive action (e.g. "see borrower" with no current loan): greyed, not a
   link, but still shows its tooltip on hover. */
.dt-action--disabled {
    opacity: 0.4;
    cursor: default;
}

/* Banner shown above a list opened pre-filtered from a dashboard stat card. */
.list-filter-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.5rem;
    padding: 0.4rem 0.75rem;
    background-color: #fff4dd;
    border: 1px solid #e0a229;
    border-radius: var(--radius);
    font-size: 0.9rem;
}

.list-filter-banner__clear {
    white-space: nowrap;
    font-weight: 600;
}

.dt__table tr.clickable-row:hover td {
    background-color: #f7f9fb;
}

.loan-items-section {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1rem;
    margin-top: 1.25rem;
    /* Fieldsets default to min-inline-size: min-content, so the wide selected-
       materials table would stretch the whole section past a phone screen
       instead of scrolling inside its wrapper. */
    min-inline-size: 0;
}

.loan-lookup {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.loan-lookup .form-field__input {
    min-width: 240px;
}

.loan-lookup__msg {
    font-size: 0.85rem;
    color: var(--color-muted);
}

.loan-lookup__msg--error {
    color: var(--color-error-text);
}

.loan-items__empty {
    color: var(--color-muted);
    font-size: 0.9rem;
    margin: 0;
}

.loan-items__table td {
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--color-border);
}

.loan-items__action {
    text-align: right;
    width: 1%;
    white-space: nowrap;
}

.return-table {
    margin-top: 0.5rem;
}

.return-table td {
    vertical-align: middle;
}

/* --- DataTable row status tints (available stays untinted) --- */
.dt__row--status-borrowed td {
    background-color: #eef4fb;
}

.dt__row--status-missing td {
    background-color: #fdeceb;
}

.dt__row--status-under_repair td {
    background-color: #fdf6ea;
}

.dt__row--status-archived td {
    background-color: #f1f2f4;
}

/* Utilisateurs page tabs (Élèves / Enseignants / Utilisateurs). A segmented
   bar above the table; the active tab connects to the table below it. */
.user-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 16px;
    border-bottom: 2px solid var(--color-border);
}

/* While a global search widens the rows to every category (see UserListPage),
   the tabs dim and a note on the bar says why. */
.user-tabs--searching .user-tabs__tab {
    opacity: 0.45;
}

.user-tabs__scope-note {
    display: none;
    align-self: center;
    margin-left: 0.5rem;
    font-size: 0.85rem;
    color: var(--color-muted);
    white-space: nowrap;
}

.user-tabs--searching .user-tabs__scope-note {
    display: inline;
}

.user-tabs__tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    margin-bottom: -2px;
    border: none;
    border-bottom: 2px solid transparent;
    background: none;
    font: inherit;
    font-weight: 600;
    color: var(--color-muted);
    cursor: pointer;
    border-radius: var(--radius) var(--radius) 0 0;
    transition: color 0.12s, background-color 0.12s, border-color 0.12s;
}

.user-tabs__tab:hover {
    color: var(--color-text);
    background-color: var(--color-bg);
}

.user-tabs__tab[aria-selected="true"] {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
}

.user-tabs__count {
    min-width: 20px;
    padding: 1px 7px;
    border-radius: 999px;
    background-color: var(--color-border);
    color: var(--color-muted);
    font-size: 0.78rem;
    font-weight: 700;
    text-align: center;
}

.user-tabs__tab[aria-selected="true"] .user-tabs__count {
    background-color: var(--color-primary);
    color: #ffffff;
}

.user-tabs__tab:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* Cross-table row state tints (pastel): late (red), borrowed (green), broken
   (blue). Applied by each list page's rowClass. */
.dt__row--late td {
    background-color: var(--row-late, #fdeae8);
}

.dt__row--borrowed td {
    background-color: var(--row-borrowed, #e7f5ec);
}

.dt__row--broken td {
    background-color: var(--row-broken, #e6f0fb);
}

/* Selected row in the loan picker. */
.dt__row--selected td {
    background-color: #e3f3e8;
}

.dt__row--selected:hover td {
    background-color: #d8eede;
}

/* --- Loan picker select button --- */
.btn--small {
    padding: 0.25rem 0.6rem;
    font-size: 0.8rem;
}

.btn--selected {
    background-color: var(--color-ok-text);
    color: #fff;
    border-color: var(--color-ok-text);
}

.btn--selected:hover {
    background-color: #176436;
}

.loan-selected-count {
    font-size: 0.9rem;
    color: var(--color-muted);
    margin: 0.25rem 0 0.5rem;
}

.loan-selected-count #loan-selected-count {
    font-weight: 700;
    color: var(--color-text);
}

/* Quantity stepper in the material picker (− [n] +). */
.qty-control {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

.qty-control__btn {
    min-width: 1.9rem;
    padding-left: 0;
    padding-right: 0;
    font-weight: 700;
    line-height: 1;
}

.qty-control__btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Banner shown on the users list when picking a loan borrower. */
.select-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.6rem 0.9rem;
    margin-bottom: 0.75rem;
    border: 1px solid var(--color-border);
    border-left: 4px solid var(--color-primary);
    border-radius: var(--radius);
    background: #f0f6ff;
    font-weight: 600;
}

/* Borrower picker field on the new-loan form. */
.borrower-pick {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.borrower-pick__name {
    flex: 1;
    min-width: 0;
}

/* "× N" tag for grouped identical loan items. */
.item-qty {
    display: inline-block;
    margin-left: 0.35rem;
    padding: 0 0.4rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    font-size: 0.85rem;
}

.qty-control__input {
    width: 3.25rem;
    text-align: center;
    padding: 0.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

/* --- Selected materials summary (chips) --- */
.loan-selected-table-wrap {
    margin-top: 0.4rem;
    overflow-x: auto;
}

.loan-selected-table {
    width: 100%;
}

.borrow-blocked {
    margin: 0 0 1.25rem;
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius);
    background-color: #fdf6ea;
    color: #8a5a12;
    font-size: 0.9rem;
}

/* --- Material picker modal --- */
.picker-modal {
    position: fixed;
    inset: 0;
    z-index: 60;
    background-color: rgba(31, 39, 51, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.picker-modal[hidden] {
    display: none;
}

.picker-modal__dialog {
    background-color: var(--color-surface);
    border-radius: var(--radius);
    width: 100%;
    max-width: 880px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.picker-modal__head,
.picker-modal__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.9rem 1.1rem;
}

.picker-modal__head {
    border-bottom: 1px solid var(--color-border);
}

.picker-modal__foot {
    border-top: 1px solid var(--color-border);
}

.picker-modal__title {
    margin: 0;
    font-size: 1.05rem;
}

.picker-modal .datatable-mount {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0.75rem 1.1rem;
    overflow: hidden;
    display: flex;
}

.picker-modal .dt {
    max-height: 100%;
    border: none;
    width: 100%;
}

/* --- Generic modal (history, etc.) --- */
.app-modal {
    position: fixed;
    inset: 0;
    z-index: 60;
    background-color: rgba(31, 39, 51, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.app-modal[hidden] {
    display: none;
}

.app-modal__dialog {
    background-color: var(--color-surface);
    border-radius: var(--radius);
    width: 100%;
    max-width: 820px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.app-modal__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.9rem 1.1rem;
    border-bottom: 1px solid var(--color-border);
}

.app-modal__title {
    margin: 0;
    font-size: 1.05rem;
}

.app-modal__body {
    overflow: auto;
    padding: 0.5rem 1.1rem 1rem;
}

/* --- Small screens --- */
@media (max-width: 720px) {
    /* Keep the stat cards legible on small screens: two per row regardless of
       the per-page column count. */
    .stat-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .material-sheet {
        grid-template-columns: 1fr;
    }

    .form-grid {
        grid-template-columns: 1fr;
    }

    .detail-list {
        grid-template-columns: 1fr;
        gap: 0;
    }

    /* Stacked label/value pairs are hard to read; a line above each label
       separates the fields clearly. */
    .detail-list dt {
        margin-top: 0.55rem;
        padding-top: 0.55rem;
        border-top: 1px solid var(--color-border);
    }
    .detail-list dt:first-of-type {
        margin-top: 0;
        padding-top: 0;
        border-top: 0;
    }
    .detail-list dd {
        margin-bottom: 0.1rem;
    }
}

@media (max-width: 600px) {
    .diagnostic__table thead {
        display: none;
    }

    .diagnostic__table,
    .diagnostic__table tbody,
    .diagnostic__table tr,
    .diagnostic__table td {
        display: block;
        width: 100%;
    }

    .diagnostic__table tr {
        border-bottom: 1px solid var(--color-border);
        padding: 0.4rem 0;
    }

    .diagnostic__table td {
        border-bottom: none;
        padding: 0.3rem 0.9rem;
    }
}

/* ============================================================ Settings page */
.settings-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.settings-toolbar__search {
    flex: 1 1 280px;
    min-width: 220px;
    padding: 8px 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font: inherit;
}

.settings-toolbar__buttons {
    display: flex;
    gap: 8px;
}

.settings-tree {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    overflow: hidden;
}

/* Collapsible branches. Each level is indented a little further. */
.settings-node {
    border-top: 1px solid var(--color-border);
}
.settings-tree > .settings-node:first-child {
    border-top: none;
}

.settings-node__title {
    cursor: pointer;
    padding: 9px 14px;
    font-weight: 600;
    color: var(--color-text);
    list-style: none;
    user-select: none;
}
.settings-node__title::-webkit-details-marker {
    display: none;
}
.settings-node__title::before {
    content: '▸';
    display: inline-block;
    width: 1em;
    color: var(--color-muted);
    transition: transform 0.12s;
}
.settings-node[open] > .settings-node__title::before {
    transform: rotate(90deg);
}

.settings-node--app > .settings-node__title {
    background: var(--color-bg);
    font-size: 1.02rem;
    cursor: default;
}
/* The root is always open, so it shows no disclosure arrow. */
.settings-node--app > .settings-node__title::before {
    content: '';
    width: 0;
}
.settings-node--module > .settings-node__title {
    color: var(--color-primary);
}
.settings-node--category > .settings-node__title,
.settings-node--subcategory > .settings-node__title {
    font-weight: 500;
    color: var(--color-muted);
    text-transform: uppercase;
    font-size: 0.78rem;
    letter-spacing: 0.02em;
}

.settings-node__body {
    padding-left: 14px;
}

/* A setting row: label/description · value · actions. */
.settings-row {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 9px 14px;
    border-top: 1px solid var(--color-border);
}
.settings-row__main {
    flex: 1 1 auto;
    min-width: 0;
}
.settings-row__label {
    font-weight: 500;
}
.settings-row__desc {
    font-size: 0.83rem;
    color: var(--color-muted);
    margin-top: 2px;
}

.settings-row__value {
    flex: 0 1 320px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    text-align: right;
}
.settings-row__value-text {
    font-variant-numeric: tabular-nums;
    color: var(--color-text);
    word-break: break-word;
}
.settings-row__editor {
    display: inline-flex;
    align-items: center;
}
.settings-row__input {
    padding: 5px 8px;
    border: 1px solid var(--color-primary);
    border-radius: 6px;
    font: inherit;
    max-width: 280px;
}
.settings-row__check {
    width: 18px;
    height: 18px;
}
.settings-row__color {
    width: 44px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background: none;
    cursor: pointer;
}
.settings-color-swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--color-border);
    vertical-align: -2px;
}
.settings-row__error {
    font-size: 0.8rem;
    color: var(--color-error-text);
}

.settings-row__actions {
    flex: 0 0 auto;
    display: flex;
    gap: 4px;
    align-items: center;
}
.settings-icon-btn {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background: var(--color-surface);
    color: var(--color-muted);
    cursor: pointer;
    font-size: 0.95rem;
    line-height: 1;
    transition: background-color 0.12s, color 0.12s, border-color 0.12s;
}
.settings-icon-btn:hover {
    background: var(--color-bg);
    color: var(--color-text);
    border-color: var(--color-primary);
}
.settings-icon-btn:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 1px;
}
.settings-row__readonly {
    font-size: 0.72rem;
    color: var(--color-muted);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    padding: 2px 9px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

@media (max-width: 720px) {
    .settings-row {
        flex-wrap: wrap;
    }
    .settings-row__value {
        flex-basis: 100%;
        align-items: flex-start;
        text-align: left;
    }
}

/* ====================================================== Roles & permissions */
.roles-toolbar {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-bottom: 12px;
}
.roles-toolbar__search {
    flex: 1 1 320px;
    max-width: 480px;
    padding: 8px 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font: inherit;
}

.roles-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin-bottom: 12px;
    font-size: 0.82rem;
    color: var(--color-muted);
}
.roles-legend__chip { display: inline-flex; align-items: center; gap: 5px; }
.roles-legend__ro {
    margin-left: auto;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    padding: 2px 10px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.roles-type {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 4px;
    font-size: 0.72rem;
    line-height: 1;
}
.roles-type--data { background: #e6f0fb; }
.roles-type--action { background: #fdf0dd; }

.roles-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
}
.roles-table {
    border-collapse: collapse;
    width: 100%;
    font-size: 0.9rem;
}
.roles-th {
    position: sticky;
    top: 0;
    background: var(--color-bg);
    border-bottom: 2px solid var(--color-border);
    padding: 8px 10px;
    text-align: center;
    white-space: nowrap;
    z-index: 1;
}
.roles-th--item { text-align: left; min-width: 240px; }

.roles-grouprow--page .roles-grouprow__cell {
    background: var(--color-bg);
    font-weight: 700;
    padding: 8px 10px;
    border-top: 2px solid var(--color-border);
}
.roles-grouprow--module .roles-grouprow__cell {
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-muted);
    padding: 5px 10px 5px 22px;
    background: var(--color-surface);
}

.roles-feature__name {
    padding: 6px 10px 6px 28px;
    border-top: 1px solid var(--color-border);
    white-space: nowrap;
}
.roles-cell-td {
    position: relative;
    border-top: 1px solid var(--color-border);
    border-left: 1px solid var(--color-border);
    text-align: center;
    padding: 4px;
}

.roles-cell {
    display: inline-flex;
    gap: 2px;
    padding: 3px 5px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: none;
    cursor: pointer;
}
.roles-cell:hover:not(:disabled) { border-color: var(--color-border); background: var(--color-bg); }
.roles-cell:disabled { cursor: default; }
.roles-verb {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 17px;
    height: 17px;
    border-radius: 3px;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--color-border);
    background: transparent;
}
.roles-verb--on { color: #fff; background: var(--color-primary); }

.roles-dropdown {
    position: absolute;
    top: calc(100% + 2px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    min-width: 170px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
    padding: 6px;
    text-align: left;
}
.roles-dropdown__row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 7px;
    border-radius: 5px;
    white-space: nowrap;
    cursor: pointer;
}
.roles-dropdown__row:hover { background: var(--color-bg); }

.roles-dropdown__scope {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    padding: 6px 7px 2px;
    border-top: 1px solid var(--color-border);
    font-size: 0.82rem;
    color: var(--color-muted);
}
.roles-dropdown__scope select { font: inherit; padding: 2px 4px; }
.roles-scope-mark {
    margin-left: 5px;
    font-size: 0.6rem;
    color: var(--color-ok-text);
    background: var(--color-ok-bg);
    border-radius: 3px;
    padding: 1px 4px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* ── "A propos" page ──────────────────────────────────────────────────────── */
.about {
    max-width: 760px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.about__hero {
    display: flex;
    align-items: center;
    gap: 24px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 24px;
    box-shadow: 0 1px 2px rgba(31, 39, 51, 0.04);
}

.about__logo {
    width: 120px;
    height: 120px;
    object-fit: contain;
    flex: none;
}

.about__app {
    margin: 0;
    font-size: 1.6rem;
    color: var(--color-text);
}

.about__tagline {
    margin: 4px 0 0;
    color: var(--color-muted);
}

.about__version {
    display: inline-block;
    margin: 12px 0 0;
    padding: 2px 10px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-primary);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: 999px;
}

.about__lead {
    margin: 0;
    font-size: 1.05rem;
    line-height: 1.6;
    color: var(--color-text);
}

.about__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.about__card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 18px 20px;
}

.about__card--accent {
    border-color: color-mix(in srgb, var(--color-primary) 35%, var(--color-border));
    background: color-mix(in srgb, var(--color-primary) 5%, var(--color-surface));
}

.about__card-title {
    margin: 0 0 10px;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-muted);
}

.about__author {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--color-text);
}

.about__muted {
    margin: 4px 0 0;
    color: var(--color-muted);
    font-size: 0.9rem;
}

.about__contact {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.about__contact li {
    display: flex;
    align-items: center;
    gap: 10px;
}

.about__contact a {
    color: var(--color-primary);
    text-decoration: none;
    word-break: break-word;
}

.about__contact a:hover {
    text-decoration: underline;
}

.about__icon {
    width: 18px;
    height: 18px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    color: var(--color-primary);
}

.about__icon--phone {
    font-size: 1rem;
    line-height: 1;
    stroke: none;
    text-align: center;
}

.about__tech {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 18px 20px;
    line-height: 1.6;
}

.about__tech p {
    margin: 0;
}

.about__footer {
    text-align: center;
    padding-top: 4px;
}

@media (max-width: 640px) {
    .about__hero {
        flex-direction: column;
        text-align: center;
    }

    .about__grid {
        grid-template-columns: 1fr;
    }

    .about__contact li {
        justify-content: center;
    }
}

/* "A propos" — responsable audiovisuel (highlighted band) */
.about__manager {
    background: color-mix(in srgb, var(--color-primary) 7%, var(--color-surface));
    border: 1px solid color-mix(in srgb, var(--color-primary) 25%, var(--color-border));
    border-left: 4px solid var(--color-primary);
    border-radius: var(--radius);
    padding: 18px 20px;
}

.about__manager-name {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--color-text);
}

.about__manager-phone {
    margin: 8px 0 0;
    display: flex;
    align-items: center;
    gap: 8px;
}

.about__manager-phone a {
    color: var(--color-primary);
    text-decoration: none;
}

.about__manager-phone a:hover {
    text-decoration: underline;
}

/* Logo control on the Settings page */
.settings-logo-preview {
    max-height: 56px;
    max-width: 180px;
    width: auto;
    height: auto;
    display: block;
    padding: 6px 8px;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

/* --- Mon profil --- */
.profile {
    max-width: 640px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1.5rem;
}

.profile__head {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-bottom: 1.25rem;
}

.profile__photo {
    width: 84px;
    height: 84px;
    flex: none;
    border-radius: 50%;
    object-fit: cover;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--color-bg);
    color: var(--color-primary);
    font-size: 1.6rem;
    font-weight: 700;
    border: 1px solid var(--color-border);
}

.profile__name {
    margin: 0;
    font-size: 1.3rem;
}

.profile__username {
    margin: 0.1rem 0 0;
    color: var(--color-muted);
    font-size: 0.9rem;
}

.profile__roles {
    display: inline-block;
    margin: 0.45rem 0 0;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface));
    color: var(--color-primary);
    font-size: 0.8rem;
    font-weight: 600;
}

.profile__details {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 1.25rem;
    margin: 0;
}

.profile__details dt {
    color: var(--color-muted);
    font-size: 0.9rem;
}

.profile__details dd {
    margin: 0;
}

/* Read-only value shown inside the profile edit form */
.form-field__static {
    padding: 0.45rem 0;
    color: var(--color-text);
    word-break: break-word;
}

/* --- Material photo gallery --- */
.gallery {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.gallery__viewer {
    position: relative;
    aspect-ratio: 4 / 3;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.gallery__img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.gallery__nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.gallery__nav--prev { left: 8px; }
.gallery__nav--next { right: 8px; }
.gallery__nav:hover { background: rgba(0, 0, 0, 0.65); }

.gallery__trash {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 50%;
    background: rgba(179, 38, 30, 0.85);
    color: #fff;
    font-size: 0.95rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.gallery__trash:hover { background: rgba(179, 38, 30, 1); }

.gallery__counter {
    text-align: center;
    color: var(--color-muted);
    font-size: 0.85rem;
}

.gallery__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    align-items: center;
}

.gallery__error {
    width: 100%;
    margin: 0.2rem 0 0;
}

/* --- Live camera overlay --- */
.camera-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: #000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.camera-overlay__video {
    max-width: 100%;
    max-height: 80vh;
}

.camera-overlay__bar {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    gap: 1rem;
    padding: 1rem;
    background: rgba(0, 0, 0, 0.4);
}

.camera-overlay__error {
    color: #fff;
    background: rgba(179, 38, 30, 0.92);
    padding: 0.6rem 1rem;
    border-radius: var(--radius);
}

/* --- Mobile bottom navigation (phones) --- */
.bottom-nav { display: none; }

@media (max-width: 768px) {
    /* The top bar keeps the brand + size buttons + avatar; the link nav moves
       to the bottom. The title may ellipsize so everything stays on one row. */
    .app-header .app-nav { display: none; }
    .app-header__username,
    .app-header__role { display: none; }
    .app-header { padding: 0 0.6rem 0 0; gap: 0.4rem; }
    .app-header__brand { min-width: 0; }
    /* Centre the title in the bar (no nav links on phones). Absolutely centred
       and width-capped so it never overlaps the logo or the avatar. */
    .app-header__brand-text {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        max-width: 46vw;
        text-align: center;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Content sits between the fixed header and the fixed bottom nav. */
    .app-main { bottom: 56px; }
    .app-footer { display: none; }

    .bottom-nav {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        height: 56px;
        z-index: 30;
        background: var(--header-bg);
        color: var(--header-text);
        border-top: 1px solid rgba(255, 255, 255, 0.18);
        justify-content: space-around;
        align-items: stretch;
    }
}

.bottom-nav__item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 4px 0;
    background: transparent;
    border: 0;
    color: inherit;
    text-decoration: none;
    font-size: 0.66rem;
    font-family: inherit;
    cursor: pointer;
    opacity: 0.85;
}

.bottom-nav__item.is-active { opacity: 1; font-weight: 600; }
.bottom-nav__item .icon { width: 22px; height: 22px; }
.bottom-nav__item span { line-height: 1; }

/* --- Bottom sheet (Gestion / Autres) --- */
.bottom-sheet {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, 0.4);
    display: flex;
    align-items: flex-end;
}

.bottom-sheet[hidden] { display: none; }

.bottom-sheet__panel {
    width: 100%;
    max-height: 70vh;
    overflow-y: auto;
    padding: 0.4rem 0.75rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
    background: var(--color-surface);
    border-radius: 16px 16px 0 0;
    transform: translateY(100%);
    transition: transform 0.2s ease;
}

.bottom-sheet.is-open .bottom-sheet__panel { transform: translateY(0); }

.bottom-sheet__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem;
    font-weight: 600;
    color: var(--color-text);
}

.bottom-sheet__close {
    background: transparent;
    border: 0;
    font-size: 1.1rem;
    color: var(--color-muted);
    cursor: pointer;
}

.bottom-sheet__link {
    display: block;
    padding: 0.85rem 0.6rem;
    border-radius: var(--radius);
    color: var(--color-text);
    text-decoration: none;
    font-size: 1rem;
}

.bottom-sheet__link:hover { background: var(--color-bg); }

/* --- Phase 2: mobile form/page polish (phones) --- */
@media (max-width: 768px) {
    /* Page-header action buttons: one slim swipeable row under the title
       (wrapping stacked them 2-3 rows high, pushing the table off-screen). */
    .page-header__actions {
        flex-wrap: nowrap;
        overflow-x: auto;
        max-width: 100%;
    }
    .page-header__actions > * {
        flex: 0 0 auto;
    }
    .page-header__actions .btn {
        white-space: nowrap;
    }

    /* User-list tabs (Élèves / Enseignants / Utilisateurs): one swipeable row
       too — wrapped, they cost two tall rows above the table. */
    .user-tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        margin-bottom: 8px;
    }
    .user-tabs__tab {
        flex: 0 0 auto;
        white-space: nowrap;
        padding: 6px 10px;
    }

    /* DataTable toolbar: the search takes a full row, the controls the next. */
    .dt__search {
        flex: 1 1 100%;
    }
    .dt__search-input {
        flex: 1;
        width: 100%;
        min-width: 0;
    }
    .dt__toolbar-right {
        flex-wrap: wrap;
    }

    /* Long min-widths would force horizontal overflow on a phone. */
    .loan-lookup .form-field__input {
        min-width: 0;
    }

    /* Comfortable touch targets. */
    .btn {
        padding: 0.6rem 1rem;
    }
    .form-actions {
        flex-wrap: wrap;
    }
}

/* --- Phase 2: reclaim edge space on phones (screen width is precious) --- */
@media (max-width: 768px) {
    .app-main {
        padding: 0.8rem 0.6rem;
    }
    .app-main--wide {
        /* No bottom padding: the table fills flush down to the menu. */
        padding: 0.5rem 0.45rem 0;
    }

    .material-form,
    .material-sheet__main {
        padding: 0.9rem;
    }
    .profile {
        padding: 1rem;
    }
    .login {
        margin-top: 1rem;
        padding: 1.1rem;
    }

    .about,
    .about__hero,
    .about__card,
    .about__tech,
    .about__manager {
        padding: 1rem;
    }
    .about { padding: 0; gap: 14px; }

    .page-header { margin-bottom: 0.75rem; }
}

/* --- Phase 3: data tables on phones (horizontal scroll) --- */
@media (max-width: 768px) {
    /* Keep columns at their content width and let the wrapper scroll sideways
       (chosen "horizontal scroll" baseline) instead of squishing every column
       and wrapping cells into tall, unreadable stacks. Row-action icons stay in
       the last column, reachable by swiping right. */
    .dt__table {
        width: max-content;
        min-width: 100%;
    }
    .dt__table td {
        white-space: nowrap;
    }

    /* No footer on phones (the bottom nav is 56px). The exact height is set by
       fitWideTables; this cap just stays above it so it never clips the fill. */
    .dt {
        max-height: calc(100vh - var(--header-height) - 56px);
    }
    /* Full-bleed on phones so the table + pagination strip span edge-to-edge. */
    .app-main--wide .dt {
        margin-left: -0.45rem;
        margin-right: -0.45rem;
        border-left: 0;
        border-right: 0;
        border-bottom: 0;
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0;
    }

    /* The list lives in a shutter ("Liste du matériel/des prêts/…"). Drop its
       body padding and bottom margin and full-bleed it so the table fills the
       width and the pagination strip sits flush above the menu. The table's own
       constrained height (.dt max-height + fitWideTables) is what makes the rows
       scroll between the sticky header and the footer. */
    .app-main--wide .shutter[data-shutter="list"] {
        margin-left: -0.45rem;
        margin-right: -0.45rem;
        margin-bottom: 0;
        border-left: 0;
        border-right: 0;
        border-bottom: 0;
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0;
    }
    .app-main--wide .shutter[data-shutter="list"] .shutter__body {
        padding: 0;
    }
    .app-main--wide .shutter[data-shutter="list"] .dt {
        margin: 0;
        border-left: 0;
        border-right: 0;
        border-bottom: 0;
        border-radius: 0;
    }

    /* The "Liste des …" bar is redundant under the page title on a phone: hide
       it to free a row (initShutters force-opens the pane so a saved "closed"
       state cannot leave the table unreachable). */
    .app-main--wide .shutter[data-shutter="list"] > .shutter__title {
        display: none;
    }
}

/* --- Collapsible table toolbar --- */
.dt__tools {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.dt__tools-toggle {
    display: none;
}

@media (max-width: 768px) {
    /* (a) Collapse the table controls behind a toggle to reclaim space. */
    .dt__tools-toggle {
        display: inline-flex;
        align-items: center;
        gap: 0.3rem;
        padding: 0.35rem 0.7rem;
        border: 1px solid var(--color-border);
        border-radius: var(--radius);
        background: var(--color-bg);
        font: inherit;
        font-size: 0.85rem;
        cursor: pointer;
    }
    .dt__tools {
        display: none;
        flex-basis: 100%;
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
        margin-top: 0.5rem;
    }
    .dt.dt--tools-open .dt__tools {
        display: flex;
    }

    /* The per-column "Filtrer" row folds behind "Outils" too (it is a second
       sticky header row); a dot on the toggle signals filters that are active
       while the row is hidden. */
    .dt__filter-row {
        display: none;
    }
    .dt.dt--tools-open .dt__filter-row {
        display: table-row;
    }
    .dt.dt--filtered .dt__tools-toggle::after {
        content: '';
        width: 0.45rem;
        height: 0.45rem;
        border-radius: 50%;
        background-color: var(--color-primary);
    }

    .dt__search {
        flex: 1 1 100%;
    }
    .dt__toolbar-right {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* (c) Smaller header + buttons to free vertical space. */
    .page-header__title {
        font-size: 1.15rem;
    }
    .page-header {
        gap: 0.5rem;
        margin-bottom: 0.6rem;
    }
    .btn {
        padding: 0.4rem 0.7rem;
        font-size: 0.85rem;
    }
    .btn--small {
        padding: 0.25rem 0.5rem;
    }

    /* (b) Centre custom dropdowns so they are easy to use on a phone. */
    .dt__columns-menu:not([hidden]),
    .searchselect__panel:not([hidden]) {
        position: fixed;
        top: 50%;
        left: 50%;
        right: auto;
        transform: translate(-50%, -50%);
        width: min(92vw, 360px);
        max-height: 70vh;
        overflow-y: auto;
        z-index: 60;
        box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.45), 0 12px 32px rgba(0, 0, 0, 0.35);
    }
}

/* --- Table "Plein écran" mode --- */
/* Toolbar button (frame icon), on every screen size: the table alone fills the
   viewport, above the fixed app bars; the same button or Escape restores the
   normal layout. */
.dt__fullscreen {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 0.55rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background-color: #fff;
    color: var(--color-muted);
    cursor: pointer;
}

.dt__fullscreen:hover {
    background-color: #f4f6f8;
    color: var(--color-text);
}

.dt__fullscreen svg {
    display: block;
    width: 1.05rem;
    height: 1.05rem;
}

/* Lengths inside the zoomed .app-main__inner are pre-zoom pixels (same rule as
   fitWideTables), so divide by the zoom to land exactly on the viewport. The
   heights beat the inline height set by fitWideTables (hence !important); the
   dvh line refines 100vh where supported (mobile browser URL bar). */
.dt.dt--fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    width: calc(100vw / var(--page-zoom, 1));
    height: calc(100vh / var(--page-zoom, 1)) !important;
    height: calc(100dvh / var(--page-zoom, 1)) !important;
    max-height: none;
    margin: 0;
    border: 0;
    border-radius: 0;
    /* Above the rest of the page content, below dialogs (60). */
    z-index: 50;
}

/* .app-main is a stacking context (position: fixed), so no z-index inside it
   can paint over the app header (10) or the bottom nav (30): while a table is
   fullscreen the fixed app bars are simply hidden (the body class is toggled
   with .dt--fullscreen by the DataTable). */
body.has-dt-fullscreen .app-header,
body.has-dt-fullscreen .app-footer,
body.has-dt-fullscreen .bottom-nav {
    display: none;
}

/* --- Page zoom: 5 "A" size buttons in the top bar --- */
/* (c/d) Zoom the page content (text, table columns and controls) on every
   screen size. The top bar and footer live outside .app-main, so the logo,
   title, size selector, avatar and footer are never affected by the zoom. */
.app-main__inner {
    zoom: var(--page-zoom, 1);
}

/* The control sits in the app header: a single "A" (shown at the chosen size)
   that opens a drop-down listing every size. */
.page-zoom {
    position: relative;
    display: inline-flex;
    align-items: center;
}
.page-zoom__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.4rem;
    height: 1.4rem;
    padding: 0 0.25rem;
    /* Blend into the (themeable) header instead of a stark white box; the same
       translucent overlay as the role pill works on any header colour. */
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.18);
    color: var(--header-text);
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}
.page-zoom__toggle[data-level="0"] { font-size: 0.4rem; }
.page-zoom__toggle[data-level="1"] { font-size: 0.48rem; }
.page-zoom__toggle[data-level="2"] { font-size: 0.56rem; }
.page-zoom__toggle[data-level="3"] { font-size: 0.64rem; }
.page-zoom__toggle[data-level="4"] { font-size: 0.72rem; }

/* Hidden state must win over the display:flex below (author CSS beats the UA
   [hidden] rule), so the drop-down actually closes after a choice. */
.page-zoom__menu[hidden] {
    display: none;
}
.page-zoom__menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
    padding: 0.3rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
}
.page-zoom__option {
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: #1f2933;
    padding: 0.2rem 1rem;
    font-weight: 700;
    line-height: 1.1;
    cursor: pointer;
    text-align: center;
}
.page-zoom__option:hover {
    background: #eef2f6;
}
.page-zoom__option:nth-child(1) { font-size: 0.6rem; }
.page-zoom__option:nth-child(2) { font-size: 0.85rem; }
.page-zoom__option:nth-child(3) { font-size: 1.15rem; }
.page-zoom__option:nth-child(4) { font-size: 1.4rem; }
.page-zoom__option:nth-child(5) { font-size: 1.7rem; }
.page-zoom__option.is-active {
    border-color: var(--color-primary);
    box-shadow: inset 0 0 0 2px var(--color-primary);
}

@media (max-width: 768px) {
    /* (a) Drop the toolbar padding so the "Outils" bar is flush, full-width and
       aligned with the "Pagination" bar and the table rows. */
    .dt__toolbar {
        padding: 0;
        border-bottom: 0;
    }
    /* (e) Tools toggle as a shutter bar with a large left arrow (closed by
       default). It stretches instead of taking the full width, so the
       "Plein écran" button shares its row instead of costing one of its own. */
    .dt__tools-toggle {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        flex: 1 1 auto;
        min-width: 0;
        padding: 0.3rem 0.6rem;
        border: 1px solid var(--color-border);
        border-radius: var(--radius);
        background: var(--table-bar-bg, #e4e6e8);
        font: inherit;
        font-weight: 600;
        text-align: left;
        cursor: pointer;
    }
    .dt__tools-toggle::before {
        content: "▸";
        font-size: 1.4rem;
        line-height: 1;
        transition: transform 0.15s ease;
    }
    .dt.dt--tools-open .dt__tools-toggle::before {
        transform: rotate(90deg);
    }

    /* (f) Separate stacked form fields with a line so they are easy to tell apart. */
    .form-grid > .form-field {
        border-bottom: 1px solid var(--color-border);
        padding-bottom: 0.7rem;
    }
    .form-grid > .form-field:last-child {
        border-bottom: 0;
        padding-bottom: 0;
    }
}

/* --- Collapsible pagination footer (phones) --- */
.dt__footer-toggle { display: none; }

@media (max-width: 768px) {
    .dt__footer-toggle {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        width: 100%;
        margin: 0;
        padding: 0.3rem 0.6rem;
        border: 0;
        border-top: 1px solid var(--color-border);
        border-radius: 0;
        background: var(--table-bar-bg, #e4e6e8);
        font: inherit;
        font-weight: 600;
        text-align: left;
        cursor: pointer;
    }
    /* Same caret behaviour as the "Outils" bar: points right when closed, rotates
       to point down when open. */
    .dt__footer-toggle::before {
        content: "▸";
        font-size: 1.4rem;
        line-height: 1;
        transition: transform 0.15s ease;
    }
    .dt.dt--footer-open .dt__footer-toggle::before {
        transform: rotate(90deg);
    }
    .dt__footer {
        display: none;
        margin: 0;
        padding: 0.5rem 0.6rem;
        background: var(--color-surface);
        border-top: 1px solid var(--color-border);
    }
    .dt.dt--footer-open .dt__footer {
        display: flex;
    }
}

/* --- CSV import page --- */
.import-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1.25rem;
    margin-bottom: 1rem;
}
.import-card__title {
    margin: 0 0 0.5rem;
    font-size: 1.05rem;
}
.import-errors {
    margin: 0.5rem 0 0;
    padding-left: 1.2rem;
    font-size: 0.9rem;
}
.import-errors li {
    margin-bottom: 0.25rem;
}

/* --- Import page tabs --- */
.import-tabs {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 1rem;
    flex-wrap: wrap;
}
.import-tab {
    padding: 0.6rem 1rem;
    border: 0;
    background: transparent;
    font: inherit;
    font-weight: 600;
    color: var(--color-muted);
    border-bottom: 2px solid transparent;
    cursor: pointer;
}
.import-tab.is-active {
    color: var(--color-text);
    border-bottom-color: var(--color-primary);
}
.import-pane { display: none; }
.import-pane.is-active { display: block; }
.import-toolbar {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

/* --- Import preview: editable cells --- */
.import-edit-cell {
    width: 100%;
    min-width: 6.5rem;
    border: 1px solid transparent;
    background: transparent;
    padding: 0.2rem 0.3rem;
    font: inherit;
    color: inherit;
    border-radius: 4px;
}
.is-editing .import-edit-cell {
    border-color: var(--color-border);
    background: #fff;
}
.is-editing .import-edit-cell:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: -1px;
}

/* ---------------------------------------------------------------------------
   Loan form: linked-accessory tree ("Matériel lié")
--------------------------------------------------------------------------- */
.loan-linked-row td:first-child {
    padding-left: 1.75rem;
}
.loan-linked-row__label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
}
.loan-linked-row__warn {
    color: #a15c07;
    font-size: 0.85em;
}

/* On phones the summary table scrolls sideways; the accessory rows instead
   stack (checkbox line, then the availability warning underneath) so the
   warning is never hidden off-screen. */
@media (max-width: 768px) {
    .loan-linked-row,
    .loan-linked-row td {
        display: block;
        white-space: normal;
    }
    .loan-linked-row td:first-child {
        padding-left: 1.2rem;
        border-bottom: 0;
        /* The summary table is wider than the screen (sideways scroll); cap the
           accessory line to the visible width (minus the left offsets: page,
           fieldset and cell padding) so its text wraps instead. */
        max-width: calc(100vw - 5rem);
    }
    .loan-linked-row td:last-child {
        max-width: calc(100vw - 5rem);
    }
    .loan-linked-row td:last-child {
        padding-top: 0;
    }
    .loan-linked-row td:last-child:empty {
        display: none;
    }
    .loan-linked-row__warn {
        padding-left: 2.9rem;
    }
}

/* Login: discreet link to the data-protection notice */
.login__privacy {
    margin: 0.9rem 0 0;
    text-align: center;
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------------------
   Notification badge: unread-messages count in the navigation
--------------------------------------------------------------------------- */
.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #d63d3d;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1;
    margin-left: 0.4rem;
    vertical-align: middle;
}

/* Corner variant: pinned to the top-right of its (relative) toggle button. */
.app-nav__more-btn,
.bottom-nav__item {
    position: relative;
}
.nav-badge--corner {
    position: absolute;
    top: -4px;
    right: -6px;
    margin: 0;
}
.bottom-nav__item .nav-badge--corner {
    top: 2px;
    right: auto;
    left: calc(50% + 8px);
}

/* Settings: e-mail recipient list editor (type email_list) */
.settings-email-list {
    display: block;
}
.settings-email-list__items {
    list-style: none;
    margin: 0 0 0.4rem;
    padding: 0;
}
.settings-email-list__item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin: 0 0.4rem 0.3rem 0;
    padding: 0.15rem 0.3rem 0.15rem 0.6rem;
    background: #eef4fb;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    font-size: 0.85rem;
}
.settings-email-list__add {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}
.settings-email-list__hint {
    margin-top: 0.3rem;
    color: #b3600a;
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------------------
   Role simulation ("Prendre le rôle de…")
--------------------------------------------------------------------------- */
.sim-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: #b3600a;
    color: #fff;
    border-radius: 999px;
    padding: 0.2rem 0.35rem 0.2rem 0.75rem;
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
}
.sim-pill__form { display: inline-flex; margin: 0; }
.sim-pill__stop {
    border: 0;
    border-radius: 999px;
    padding: 0.2rem 0.6rem;
    background: #fff;
    color: #b3600a;
    font: inherit;
    font-size: 0.75rem;
    font-weight: 700;
    cursor: pointer;
}
.sim-pill__stop:hover { background: #fdf6ea; }
@media (max-width: 768px) {
    /* Compact on phones: the pill stays visible next to the avatar. */
    .sim-pill { position: fixed; top: calc(var(--header-height) + 6px); right: 8px; z-index: 35; box-shadow: 0 2px 8px rgba(0,0,0,0.25); }
}

/* Role picker cards */
.sim-roles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 0.8rem;
    margin: 1rem 0;
}
.sim-roles__card {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    padding: 0.9rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    align-items: flex-start;
}
.sim-roles__label { font-weight: 700; }
.sim-roles__desc { font-size: 0.85rem; color: var(--color-muted); }
.sim-roles__card .btn { margin-top: auto; }

/* Settings: maintenance danger zone (test-data purge) */
.danger-zone {
    margin-top: 1.5rem;
    border: 1px solid #d99a2b;
    border-radius: var(--radius);
    background: #fdf6ea;
    padding: 1rem 1.25rem;
}
.danger-zone__title {
    margin: 0 0 0.5rem;
    font-size: 1.05rem;
    color: #b3600a;
}
.danger-zone__text {
    font-size: 0.9rem;
    margin: 0 0 0.8rem;
}

/* In-place confirmation strip (forms with data-confirm — no popups) */
.confirm-strip {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.7rem;
    border: 1px solid #d99a2b;
    border-radius: var(--radius);
    background: #fdf6ea;
}
.confirm-strip__text {
    font-size: 0.88rem;
    color: #7a4a06;
    font-weight: 600;
}

/* Armed state of the gallery trash button (two-step delete) */
.gallery__trash--armed {
    background: #b02a2a !important;
    color: #fff !important;
    font-size: 0.8rem;
}

/* Inline export status (replaces alert popups) */
.export-note {
    margin-left: 0.5rem;
    font-size: 0.85rem;
    color: #b3600a;
}
