html, body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; } h1:focus { outline: none; } a, .btn-link { color: #0071c1; } .btn-primary { color: #fff; background-color: #1b6ec2; border-color: #1861ac; } .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; } .content { padding-top: 1.1rem; } .valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; } .invalid { outline: 1px solid red; } .validation-message { color: red; } #blazor-error-ui { color-scheme: light only; background: lightyellow; bottom: 0; box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); box-sizing: border-box; display: none; left: 0; padding: 0.6rem 1.25rem 0.7rem 1.25rem; position: fixed; width: 100%; z-index: 1000; } #blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; } .blazor-error-boundary { background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; padding: 1rem 1rem 1rem 3.7rem; color: white; } .blazor-error-boundary::after { content: "An error has occurred." } .loading-progress { position: absolute; display: block; width: 8rem; height: 8rem; inset: 20vh 0 auto 0; margin: 0 auto 0 auto; } .loading-progress circle { fill: none; stroke: #e0e0e0; stroke-width: 0.6rem; transform-origin: 50% 50%; transform: rotate(-90deg); } .loading-progress circle:last-child { stroke: #1b6ec2; stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; transition: stroke-dasharray 0.05s ease-in-out; } .loading-progress-text { position: absolute; text-align: center; font-weight: bold; inset: calc(20vh + 3.25rem) 0 auto 0.2rem; } .loading-progress-text:after { content: var(--blazor-load-percentage-text, "Loading"); } code { color: #c02d76; } .form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder { color: var(--bs-secondary-color); text-align: end; } .form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder { text-align: start; } /* ------------------------------------------------------------------ MaBibli — interface du catalogue (phase 3) Conçue mobile d'abord : une seule colonne, cibles tactiles d'au moins 2,75 rem, aucune règle de largeur en dessous du point de rupture. Le PC n'ajoute qu'une largeur maximale et une grille de cartes. ------------------------------------------------------------------ */ :root { --mb-accent: #1b3a5c; --mb-bord: #dcdcdc; --mb-fond-doux: #f4f5f7; --mb-texte-doux: #5c6470; --mb-danger: #a4242c; } body { background: #fff; color: #1d2129; } .titre-page { font-size: 1.4rem; margin: 0 0 0.75rem; } .message-discret { color: var(--mb-texte-doux); font-size: 0.9rem; } .message-erreur { background: #fdecec; border-left: 3px solid var(--mb-danger); color: #7a1a20; padding: 0.6rem 0.75rem; border-radius: 4px; margin: 0.75rem 0; } .message-avertissement { background: #fff8e1; border-left: 3px solid #c99700; color: #6b5200; padding: 0.6rem 0.75rem; border-radius: 4px; margin: 0.5rem 0; font-size: 0.9rem; } .compteur { color: var(--mb-texte-doux); font-size: 0.85rem; margin: 0.75rem 0 0.25rem; } /* --- Champs de saisie --- */ .barre-recherche { margin-bottom: 0.75rem; } .champ { display: block; margin-bottom: 0.9rem; border: 0; padding: 0; } .champ-libelle { display: block; font-size: 0.85rem; font-weight: 600; margin-bottom: 0.3rem; } .champ-aide, .obligatoire { font-weight: 400; color: var(--mb-texte-doux); } .champ-saisie { width: 100%; /* 16px minimum : en dessous, iOS zoome au focus. */ font-size: 1rem; padding: 0.7rem 0.75rem; border: 1px solid var(--mb-bord); border-radius: 8px; background: #fff; } .champ-saisie:focus { outline: 2px solid var(--mb-accent); outline-offset: -1px; } /* --- Segments (filtres, format, statut) --- */ .segments { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.5rem; } .segment { flex: 1 1 auto; min-height: 2.5rem; padding: 0.4rem 0.7rem; font-size: 0.85rem; border: 1px solid var(--mb-bord); border-radius: 999px; background: #fff; color: #1d2129; cursor: pointer; } .segment-actif { background: var(--mb-accent); border-color: var(--mb-accent); color: #fff; } .segments-compacts .segment { min-height: 2.2rem; font-size: 0.8rem; } .segment.statut-a-lire.segment-actif { background: #6b4fa8; border-color: #6b4fa8; } .segment.statut-en-cours.segment-actif { background: #b06b00; border-color: #b06b00; } .segment.statut-lu.segment-actif { background: #1f7a44; border-color: #1f7a44; } /* --- Boutons --- */ .bouton { display: inline-flex; align-items: center; justify-content: center; min-height: 2.75rem; padding: 0.6rem 1rem; border-radius: 8px; border: 1px solid var(--mb-bord); background: #fff; color: #1d2129; font-size: 0.95rem; text-decoration: none; cursor: pointer; } .bouton:disabled { opacity: 0.55; cursor: default; } .bouton-principal { background: var(--mb-accent); border-color: var(--mb-accent); color: #fff; } .bouton-discret { background: var(--mb-fond-doux); } .bouton-danger { background: var(--mb-danger); border-color: var(--mb-danger); color: #fff; } .actions-formulaire { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; } .actions-flottantes { position: fixed; left: 0; right: 0; bottom: 0; display: flex; gap: 0.5rem; padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom)); background: rgba(255, 255, 255, 0.96); border-top: 1px solid var(--mb-bord); } .actions-flottantes .bouton { flex: 1; } /* --- Couvertures --- */ .couverture { position: relative; flex: 0 0 auto; overflow: hidden; border-radius: 6px; background: var(--mb-fond-doux); border: 1px solid var(--mb-bord); } .couverture-petite { width: 3.5rem; height: 5.25rem; } .couverture-moyenne { width: 6rem; height: 9rem; } .couverture-substitut { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 1.5rem; font-weight: 700; color: #9aa2ad; } .couverture-image { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; } /* Posée par l'attribut onerror : les couvertures OpenLibrary renvoient des 502 intermittents, l'image cassée laisse place au substitut. */ .couverture-image.image-cassee { display: none; } /* --- Liste de livres --- */ .liste-livres, .liste-candidats { list-style: none; margin: 0; padding: 0; } .carte-livre, .carte-candidat { display: flex; gap: 0.75rem; padding: 0.75rem 0; border-bottom: 1px solid var(--mb-bord); } .carte-corps { min-width: 0; flex: 1; } .carte-titre { display: block; font-weight: 600; color: #1d2129; text-decoration: none; margin: 0 0 0.15rem; } .carte-auteur { margin: 0 0 0.25rem; color: var(--mb-texte-doux); font-size: 0.9rem; } .carte-details { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; margin: 0 0 0.5rem; font-size: 0.8rem; color: var(--mb-texte-doux); } .etiquette { background: var(--mb-fond-doux); border-radius: 4px; padding: 0.1rem 0.4rem; } /* --- Choix entre plusieurs notices --- */ /* Les candidats partagent titre et auteur : ce sont l'éditeur et l'année qui les départagent, donc ils sont mis en avant visuellement. */ .candidat-distinction { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 0.4rem; font-size: 0.9rem; } .candidat-editeur { font-weight: 600; } .candidat-annee { background: #eef2f7; border-radius: 4px; padding: 0.05rem 0.4rem; } /* --- Formulaire --- */ .formulaire-apercu { display: flex; justify-content: center; margin-bottom: 1rem; } .zone-danger { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--mb-bord); } /* --- PC : simple élargissement, la structure mobile ne change pas. --- */ @media (min-width: 48rem) { .actions-flottantes { position: static; padding: 0; margin-top: 1.5rem; background: none; border-top: 0; } .actions-flottantes .bouton { flex: 0 0 auto; } }