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

.shell { display: flex; flex-direction: column; height: 100vh; }

.topbar {
    display: flex; align-items: center; gap: 12px;
    height: 52px; padding: 0 16px; flex: 0 0 auto;
    border-bottom: 1px solid var(--bs-border-color);
    background: var(--bs-body-bg);
}
.brand { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; text-decoration: none; color: var(--bs-body-color); }

/* De AppKit-MainLayout heeft geen brand-logo-optie (AppKitOptions kent er geen), dus we vervangen het icoon
   hier: het DevExpress-SVG verbergen en de CleanOps-druppeltegel (favicon.svg) tonen - zelfde patroon als
   CreditSoft en Nimble. Kandidaat voor een echte brand-slot in de AppKit - bij ADM One gemeld. */
.topbar .brand > svg.adm-icon { display: none; }
.topbar .brand::before {
    content: "";
    width: 24px; height: 24px; flex: 0 0 auto;
    background: url("/favicon.svg") center / contain no-repeat;
}

.shell-body { display: flex; flex: 1; min-height: 0; }

.sidebar {
    flex: 0 0 220px; overflow-y: auto; padding: 12px 8px;
    border-right: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
}

.nav-menu { display: flex; flex-direction: column; gap: 2px; }
.nav-menu .nav-link {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px; border-radius: 8px;
    color: var(--bs-body-color); text-decoration: none; font-size: .92rem;
}
.nav-menu .nav-link:hover { background: var(--bs-secondary-bg); }
.nav-menu .nav-link.active { background: var(--bs-primary-bg-subtle); color: var(--adm-accent-text); font-weight: 600; }

/* ⚠️ min-height: 0 is niet optioneel. Zonder die regel krimpt dit flex-item niet onder zijn inhoudshoogte:
   het contentgebied groeit voorbij de viewport en de HELE pagina scrollt in plaats van enkel dit vak.
   Zet ze op .content ZELF — enkel op .content-inner (zoals de :has-regels verderop) repareert de binnenkant
   en laat de buitenkant stuk. */
.content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; }

/* De max-width is een bewuste LEESCAP voor formulieren en tekstpagina's: regels van 2000px lezen niet.
   Pagina's die de ruimte moeten vullen (grid, tweekoloms-werkscherm) ontsnappen eraan via de
   :has(.adm-grid-fill)-regels verderop en de :has(.adm-page-fill)-regels in adm-shell.css. Schrap deze cap dus niet — voeg een
   uitzondering toe als je een nieuw vol-formaat patroon bouwt. */
.content-inner { padding: 20px 24px; max-width: 1100px; }

/* ⚠️ VLAK EN TEKST UIT DEZELFDE FAMILIE (12/10/2026). Tot dan had de balk een VAST licht vlak (#fee) zonder eigen
   tekstkleur: in donker erfde de zin de lichte tekstkleur van het thema en de twee links de lichte accentkleur — wit op
   bijna-wit (gemeten: 1,16 en 1,87–2,40 over de elf accenten; norm 4,5). De balk verschijnt enkel wanneer het circuit
   sterft, precies wanneer iemand moet kunnen lezen wat er aan de hand is. Gemeld door de CEOS-sessie.
   Het thema levert vlak en tekst als paar, in licht en in donker; de terugval is hetzelfde paar in vaste kleuren. De
   links nemen de tekstkleur van de balk over (de accentkleur is niet voor dit vlak gekozen) en zijn onderlijnd.
   Bewaakt door ContrastBrowserTests in de AppKit, die de balk eerst zichtbaar maakt: op display:none meet niemand iets. */
#blazor-error-ui {
    display: none; position: fixed; bottom: 0; left: 0; right: 0;
    padding: 10px 16px; z-index: 1100;
    background: var(--bs-danger-bg-subtle, #fee);
    color: var(--bs-danger-text-emphasis, #58151c);
    border-top: 1px solid var(--bs-danger-border-subtle, #f5c2c7);
}
#blazor-error-ui .reload, #blazor-error-ui .dismiss { margin-left: 12px; cursor: pointer; color: inherit; text-decoration: underline; }

/* === AdmGrid (overgezet uit ADM One — playbook §6) ============================================ */
/* Accentkleur voor o.a. de selectie-balk; overschrijfbaar per thema/tenant. */
:root { --adm-accent: #2563eb; }

/* AdmGrid: uniforme toolbar (zoek + kolomselector + export) boven elke grid. */
.adm-grid-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}

.adm-grid-bar-spacer {
    flex: 1 1 auto;
}

.adm-grid-search {
    width: 300px;
    max-width: 100%;
}

.adm-grid-empty {
    padding: 18px;
    color: var(--bs-secondary-color);
    font-style: italic;
}

/* Laadfase: grid verbergen (layout wordt nog toegepast) en een spinner tonen, zodat de gebruiker
   geen herformattering ("flikker") ziet. */
.adm-grid-body { position: relative; }
.adm-grid-veil { visibility: hidden; }
/* ⚠️ `.adm-grid-fill .adm-grid-body` en `.adm-grid-fill .adm-grid-bar` STONDEN HIER, woordelijk gelijk aan
   adm-shell.css, en zijn weg op 09/09/2026 (playbook: "CSS van een fundering-component hoort IN de
   fundering"). De fundering zegt het zelf bij die regels: "Ships met het pakket zodat apps geen eigen
   .adm-grid-fill-hack in app.css meer nodig hebben — wie het element rendert, stijlt het."
   Gemeten vóór het weghalen: zelfde eigenschap én zelfde waarde (flex 1 · min-height 0 · display flex ·
   flex-direction column), dus de laadvolgorde doet er niet toe. */
.adm-grid-loading {
    position: absolute;
    inset: 0;
    min-height: 180px;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.adm-spinner {
    width: 34px;
    height: 34px;
    border: 3px solid var(--dx-color-border, #e0e0e0);
    border-top-color: var(--dx-color-primary, #2563eb);
    border-radius: 50%;
    animation: adm-spin .7s linear infinite;
}
@keyframes adm-spin { to { transform: rotate(360deg); } }

/* FullHeight: de grid vult de beschikbare hoogte (toolbar vast, grid scrollt intern). De :has-regels
   koppelen aan de layout-wrapper (.content/.content-inner — aanwezig in deze app). */
.content:has(.adm-grid-fill) {
    display: flex;
    flex-direction: column;
}
.content:has(.adm-grid-fill) > .content-inner {
    flex: 1;
    min-height: 0;
    max-width: none;   /* grid-pagina's vullen de volle breedte, niet de 1100px-leescap */
    display: flex;
    flex-direction: column;
}
/* Op een pagina met een FICHE bepaalt de fiche haar eigen breedte (.adm-fiche: max-width var(--adm-fiche-breedte, 1100px)
   in de AppKit), niet de leescap van de pagina.
   ⚠️ Waarom (15/10/2026, gezien door Dominique, gemeten en voorgesteld door CleanOps, beslist door Dominique): de leescap
   hierboven maakte een fiche bij het openen 1052 px breed (1100 min 2×24 rand), en de vulrasterregel hierboven hief ze op
   zodra er ERGENS een FullHeight-raster in de pagina stond. Een raster in een fichetabblad (het vlootadvies van Huis
   Jacobs, 13/09) komt pas in de pagina bij de eerste klik op dat tabblad: de fiche sprong dan van 1052 naar 1100 px en
   bleef zo. Nu is een fiche van bij het openen 1100 px — de breedte die ze na de klik al kreeg. Lijstpagina's, brede
   fiches (.adm-fiche-breed) en fiches zonder raster in een tab veranderen verder niet (gemeten bij CleanOps op 1440 px). */
.content:has(.adm-fiche) > .content-inner {
    max-width: none;
}
.content:has(.adm-grid-fill) > .dxbl-btn {
    align-self: flex-start;
}

/* Het vol-hoogte WERKSCHERM (`adm-page-fill`, `adm-fill-row`, `adm-fill-panel`) staat sinds AppKit 0.435.0 in adm-shell.css, mét
   scrollen onder 992px — de oude kopie hier hield de pagina onder lg vast (overflow: hidden buiten de lg-query). Weggehaald
   bij de bump (04/10/2026); CleanOps gebruikt de klassen vandaag nergens. Zet ze hier NIET terug: een app-regel wint van de
   fundering. */

/* Rijmarkering (selectie + focus) staat sinds AppKit 0.19.0 in adm-shell.css — AdmGrid komt uit het
   pakket, dus hoort zijn stijl daar ook. Zet ze hier NIET opnieuw: een app-regel wint van de fundering
   en je krijgt stil afwijkend gedrag per app. */

/* Routes.razor focust bij elke navigatie de paginatitel-<h1> (FocusOnNavigate — de schermlezer leest de titel voor).
   De fundering onderdrukt de muis-focusrand enkel via `h1:focus:not(:focus-visible)` (adm-shell.css), maar bij een
   VOLLEDIGE paginalaad (bv. het startscherm net na login) telt die focus in sommige browsers toch als
   :focus-visible → zwart kader rond de titel. Een titel is niet-interactief → nooit een zichtbare focusrand
   (ook niet bij :focus-visible). App-eigen regel, niet in de fundering (per-app opgelost, zie CreditSoft). */
h1:focus,
h1:focus-visible { outline: none; }

/* Login-scherm (fundering-LoginPanel): stijl verhuisd naar de scoped LoginPanel.razor.css in Adm.AppKit.Web. */

/* Nav: gebruiker + afmelden onderaan. */
.nav-spacer { flex: 1 1 auto; min-height: 12px; }
.nav-user { padding: 8px 12px; font-size: .82rem; color: var(--bs-secondary-color); font-weight: 600; }
.nav-section { padding: 12px 12px 4px; font-size: .72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--bs-secondary-color); }

/* === Release notes ("Wat is nieuw") ============================================================ */
.rn-page-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.release-notes { max-width: 760px; }
.rn-item { padding: 16px 0; border-bottom: 1px solid var(--bs-border-color); }
.rn-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.rn-version { font-weight: 700; }
.rn-date { color: var(--bs-secondary-color); font-size: .85rem; }
.rn-cat { font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
    padding: 2px 8px; border-radius: 10px; background: var(--bs-secondary-bg); color: var(--bs-secondary-color); }
.rn-title { font-size: 1.05rem; margin: 2px 0 6px; }
.rn-body { color: var(--bs-body-color); }
.rn-body :last-child { margin-bottom: 0; }
.rn-body img { max-width: 100%; height: auto; border-radius: 6px; }

/* Help-lade: de "Volledige handleiding"-knop volle breedte + zelfde stijl als de Afmelden-knop
   (.prefs-logout). Enkel binnen het help-paneel, zodat de thema/taal-chips een pil blijven. */
.help-panel .prefs-footer .prefs-chip {
    display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
    padding: 8px; border-radius: 8px;
}
.help-panel .prefs-footer .prefs-chip:hover { background: var(--bs-secondary-bg); }

/* ── Kopblok van een detailscherm: gegevens in twee kolommen ────────────────────────────────────────────
   De vijf detailschermen (klant, contract, factuur, offerte, werkorder) tonen hun gegevens in een `.row`
   met twee `col-md-6` binnen een max-width. Daar staat vrije tekst van de gebruiker in: een naam, een
   straat, een e-mailadres.

   ⚠️ Een e-mailadres is één ONONDERBROKEN woord en browsers breken niet op een @ of een punt. Een cel kan
   niet smaller worden dan haar langste woord. `anywhere` breekt alleen wanneer het moet en laat normale
   tekst met rust.

   GEMETEN op 24/08/2026 in de browser, tegen de echte Bootstrap en deze app.css, bij twee kolommen naast
   elkaar van 450 px:
     - positieve controle (één woord van 200 tekens): 1659 px overloop ZONDER, 0 MET  → de regel werkt
     - drempel voor een ononderbroken e-mailadres: 95 tekens
     - een realistisch lang adres van 62 tekens neemt 426 px en past dus ruim
   Mijn eerste inschatting van "~70 tekens" was fout; 70 past met 24 px over.

   Dit is dus verzekering tegen een ZELDZAAM geval, geen reparatie van iets waargenomen. Bewust toch gezet:
   het is één geërfde eigenschap, ze kost niets wanneer ze niet nodig is, en de AppKit repareerde op
   dezelfde dag drie keer exact dit patroon — telkens gevonden doordat iemand er toevallig tegenaan liep. De AppKit repareerde diezelfde dag drie keer exact dit patroon (bijlagentabel, journaalkaart,
   AdmLogList) — telkens gevonden door iemand die er toevallig tegenaan liep, niet door een controle. Zie
   0.281.0/0.282.0. */
.co-kopblok {
    overflow-wrap: anywhere;
}

/* Een SubBar met meer dan één regel — uitleg, filter, meldingen, tellers — als ÉÉN blok, zodat ze niet elk
   als losse regel in de kolom van .adm-grid vallen, met ruimte tot het raster (25/09/2026). Eerst voor
   "Te factureren", daarna ook Openstaande posten: allebei stonden die regels BOVEN de titel van de lijst. */
.ops-subbalk { margin-bottom: .75rem; }
/* Een losse melding in een SubBar (Feestdagen): dezelfde ruimte tot de lijst. ⚠️ !important omdat .mb-0 van Bootstrap er zelf een heeft. */
.ops-subbalk-melding { margin-bottom: .75rem !important; }
/* De plek van een rijmenu (AdmRowMenu, knop 28 px gemeten) in een rij zonder menu: zo staat de knop ernaast in elke rij op dezelfde
   plaats (planningslijst, 22/10/2026 — "Toewijzen" verschoof 28 px tussen rijen met en zonder volgordemenu). */
.ops-menu-plek { display: inline-block; width: 28px; flex-shrink: 0; }
/* Platformbeheer: VIER compacte tegels per rij op een breed scherm (Dominique, 22/10/2026). Het AppKit-raster zet er vijf van 192 px, en
   dan liepen zeven Franse titels ("Entreprises de traitement", "Conditions de paiement", …) en "Producten (attesten)" over twee regels —
   een titel kreeg ±130 px. Met vier ±195 px. Enkel vanaf 992 px: smaller beslist het AppKit-raster zelf. */
@media (min-width: 992px) {
    .ops-beheer-hub .tiles.tiles-compact { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Groot werk: de hele rij lichtgroen, zoals de legacy (Vw_services.pas:658-665, clMoneyGreen) — doorlichting L1-14, 09/10/2026.
   De subtle-tint van Bootstrap kleurt mee in donker thema. Op de CEL (td), want DevExpress schildert de achtergrond daar. */
.adm-grid tr.ops-rij-groot-werk > td { background-color: var(--bs-success-bg-subtle); }

/* === Historiek-tab: één rij mag het scherm niet opeten ======================================== */
/* ⚠️ GEMETEN OP PRODUCTIE (09/09/2026), contract 6211: één cel van 909px hoog met 786 tekens, in een
   viewport van 1289 — zeventig procent van het scherm voor ÉÉN regel. De oorzaak is niet een lange
   waarde maar een AANMAAK-rij: die noteert alle 43 velden van het record onder elkaar, en dat is voor
   elk geconverteerd record de eerste regel van zijn historiek. Wie de fiche opent om te zien wat er
   veranderd is, scrolt eerst langs die muur.

   `adm-historie-velden` is een klasse van de fundering (AdmRecordHistorie), en die is bevroren. Dit is
   dus opmaak aan ONZE kant boven een component dat we verder ongemoeid laten — geen kopie van het
   component, alleen een leeshoogte eromheen.

   Waarom scrollen en niet afkappen: een historiek waarin een waarde stilletjes verdwijnt is erger dan
   een lijst die je moet doorlopen. Alles blijft bereikbaar, alleen niet meer allemaal tegelijk.

   ⚠️ Lost de fundering dit ooit zelf op, dan is deze regel drift. Ze staat daarom hier en niet in een
   eigen bestand, met de meting erbij zodat een volgende sessie kan nagaan of ze nog nodig is. */
.adm-historie-velden {
    max-height: 11rem;
    overflow-y: auto;
    margin-bottom: 0;
}

/* De scrollbalk pas tonen wanneer er echt iets te scrollen valt — anders staat er een grijze streep
   naast elke rij van één veld, en die suggereert inhoud die er niet is. */
.adm-historie-velden::-webkit-scrollbar { width: 6px; }
.adm-historie-velden::-webkit-scrollbar-thumb { background: var(--bs-border-color); border-radius: 3px; }

/* De PDF-viewer in het afdrukvoorbeeld van de offerte (25/09/2026). ⚠️ De hoogte MOET via een CssClass —
   DxPdfViewer heeft geen style-parameter, en zonder hoogte rendert hij als een streepje. Zelfde oplossing
   als Nimble en CreditSoft. */
.afdruk-pdf-viewer { width: 100%; height: 70vh; }
