/*==================================================================
//
//  base.css
//
//  All FORM: layout, typografi, mått, komponenter.
//
//  HÄR FINNS INGA FÄRGER. Varenda färg hämtas som en variabel,
//  t.ex. var(--color-surface), och variablerna definieras i
//  /assets/css/theme/<tema>.css - en fil per färgtema.
//
//  Vill man byta utseende ändrar man alltså i temafilen, och vill
//  man byta form ändrar man här. Ett nytt tema kräver inte en enda
//  ändring i den här filen.
//
//  HITTAR DU EN FÄRG HÄR ÄR DET ETT FEL SOM SKA RÄTTAS. Sök på
//  "#" i filen - det ska inte ge en enda träff.
//
//  Ordning i filen:
//    1. Grundinställningar och mått
//    2. Elementen
//    3. Ramverket (header, main, footer)
//    4. Komponenter
//    5. Mindre skärmar
//
==================================================================*/


/*------------------------------------------------------------------
//
//	1. Grundinställningar och mått
//
//  Allt som är ett mått, ett avstånd eller en storlek ligger som
//  variabel här, så att proportionerna går att ändra på ett ställe.
//
------------------------------------------------------------------*/

:root {

    /* Avstånd. Skalan är avsiktligt grov - fem storlekar man kan
       hålla i huvudet slår tjugo man måste slå upp. */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;
    --space-8: 4.5rem;

    /* Textstorlekar */
    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.375rem;
    --text-2xl: 1.875rem;
    --text-3xl: 2.5rem;

    /* Rundade hörn */
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 16px;
    --radius-pill: 999px;

    /* Bredder */
    --width-page: 1100px;
    --width-text: 62ch;

    /*  Taket på innehåll som ska LÄSAS i en bred ruta.

        --width-page gör två jobb: den är ramens bredd, och därmed
        också taket på allt som ligger i den. En sida som tar hela
        fönstret sätter den till 100% (se .page--wide) - och då
        försvinner båda jobben på en gång.

        Det här måttet skrivs ALDRIG över, och är alltså det en panel
        kapar sitt innehåll vid när rutan är bred men texten i den
        inte ska vara det. Se .panel--reading. */
    --width-content: 1100px;

    /*  En smal panel, t.ex. ett inloggningsformulär.

        Ett formulär med fyra fält som breder ut sig över hela
        sidan blir svårare att läsa, inte lättare - ögat tappar
        vilken etikett som hör till vilken ruta. */
    --width-narrow: 30rem;

    /* Typsnitt. Systemets egna, inga externa - det håller sidan
       snabb och slipper ett anrop till en annan domän som CSP:n
       ändå stoppar (se __config/_session.php). */
    --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas,
                 "Liberation Mono", monospace;

    /* Rörelse */
    --transition: 160ms ease;
}


/*------------------------------------------------------------------
//
//	2. Elementen
//
------------------------------------------------------------------*/

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    /* Så att ankarlänkar inte hamnar under toppraden */
    scroll-padding-top: var(--space-7);
}

body {
    margin: 0;
    min-height: 100vh;

    display: flex;
    flex-direction: column;

    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: 1.6;

    color: var(--color-text);
    background-color: var(--color-bg);
}

h1, h2, h3 {
    margin: 0 0 var(--space-3) 0;
    line-height: 1.25;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--color-heading);
}

h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }

p {
    margin: 0 0 var(--space-4) 0;

    /*  Radlängden har ett tak.

        62 tecken är ungefär där ögat slutar hitta tillbaka till
        nästa rad utan ansträngning. En rad som går över hela en
        bred skärm läses inte, den skannas. */
    max-width: var(--width-text);
}

p:last-child {
    margin-bottom: 0;
}

a {
    color: var(--color-link);
    text-decoration: none;
    transition: color var(--transition);
}

a:hover {
    color: var(--color-link-hover);
    text-decoration: underline;
}

img {
    max-width: 100%;
    height: auto;
    display: block;
}

ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

strong {
    font-weight: 600;
    color: var(--color-heading);
}

em {
    color: var(--color-text-muted);
    font-style: normal;
}

code {
    font-family: var(--font-mono);
    font-size: 0.9em;
    padding: 0.1em 0.35em;
    border-radius: var(--radius-sm);
    background: var(--color-surface-strong);
}

/*  Tydlig markering för den som stegar med tangentbordet.

    Ligger på :focus-visible och inte på :focus, så att den som
    klickar med musen inte får en ram runt varje knapp hen rör. */
:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 3px;
    border-radius: var(--radius-sm);
}

/*  Respektera besökare som bett om mindre rörelse.

    Vissa blir illamående av animationer. Inställningen finns i
    operativsystemet och kostar oss ingenting att lyda. */
@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
        animation: none !important;
    }
}


/*------------------------------------------------------------------
//
//	3. Ramverket
//
------------------------------------------------------------------*/

/*  HOPPA TILL INNEHÅLLET

    Första länken på sidan, osynlig tills den får fokus. Den som
    stegar med tangentbordet slipper då gå igenom hela menyn på
    varje sida. Skrivs ut av layout/head.php */
.skip-link {
    position: absolute;
    left: var(--space-4);
    top: calc(var(--space-4) * -4);
    z-index: 10;

    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-md);

    color: var(--color-on-accent);
    background: var(--color-accent);

    transition: top var(--transition);
}

.skip-link:focus {
    top: var(--space-4);
}

/*  Toppraden

    Ordningen på raden är märkningens: menyknappen, logotypen,
    menyvalen, och sist besökarens egen del. Ingen order-regel
    flyttar om dem - det ögat ser och det som läses upp för den som
    lyssnar ska vara samma ordning.

    INGEN justify-content: space-between. ALLT utom logotypen skjuts
    till högerkanten av EN rad: margin-right: auto på .brand längre
    ned. Skillnaden mot space-between är att avstånden inte
    fördelas om när menyn får ett val till - logotypen står kvar
    till vänster, resten står kvar till höger, och det enda som
    ändras är hur brett "resten" är.

    position: relative är fästet för menyn som fälls ut på smala
    skärmar. Utan raden hamnar den i fönstrets övre vänstra hörn. */
.site-header {
    /*  Radens sidokant, som en egen variabel.

        Menyn som fälls ut i avsnitt 5 ska ligga i linje med
        logotypen ovanför sig och behöver alltså veta indraget.
        Variabeln ärvs ned till barnen, så måttet står på ETT
        ställe även när det ändras för en smalare skärm. */
    --header-inset: var(--space-5);

    position: relative;

    width: 100%;
    max-width: var(--width-page);
    margin: 0 auto;
    padding: var(--space-5) var(--header-inset) var(--space-4);

    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
}

/*  Sidans innehåll */
.site-main {
    flex: 1 1 auto;
    width: 100%;
    max-width: var(--width-page);
    margin: 0 auto;
    padding: var(--space-4) var(--space-5) var(--space-8) var(--space-5);

    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

/*  Sidfoten */
.site-footer {
    width: 100%;
    max-width: var(--width-page);
    margin: 0 auto;
    padding: var(--space-5);

    border-top: 1px solid var(--color-border-soft);

    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;

    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

.site-footer__choices {
    display: flex;
    gap: var(--space-5);
    flex-wrap: wrap;
}

.site-footer__legal {
    margin: 0;
    max-width: none;
}

/*  Märket för utvecklingsläget.

    TONA INTE NED DEN HÄR. Den ser skrikig ut med avsikt: märket
    finns för att en sajt som gått i drift med DEV_MODE kvar ska
    avslöja sig för den som råkar titta, och ett diskret märke hade
    inte gjort det. Skälet står i rutan i __config/config.php.

    flex-basis: 100% tar en egen rad i sidfotens flexrad, så att
    märket ligger över språkvalet och upphovsrätten i stället för
    bredvid dem. */
.site-footer__dev {
    flex-basis: 100%;
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);

    background: var(--color-danger);
    color: var(--color-on-danger);
    border-radius: var(--radius-md);

    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 0.02em;
    text-align: center;
}

/*  Mallens versionsnummer.

    Egen rad under upphovsrätten, i den svagaste texten: det är en
    upplysning till den som bygger vidare på mallen, inte något
    besökaren har ett ärende till. Se __config/version.php. */
.site-footer__version {
    display: block;
    margin-top: var(--space-1);

    font-size: var(--text-xs);
    color: var(--color-text-faint);
}

/*  EN SIDA SOM BEHÖVER HELA FÖNSTRET

    Sajtens vanliga bredd (--width-page) är vald för TEXT. En sida
    som är en tabell med tjugo kolumner blir en smal remsa man
    scrollar i sidled i stället för en översikt.

    MÅTTET ÄNDRAS PÅ ETT STÄLLE, inte per del. Variabeln sätts på
    <body> och ärvs av toppraden, innehållet och sidfoten - de tre
    reglerna ovan står orörda, och en ny bred sida kräver ingen ny
    regel här. Vilka sidor det gäller står i routes.php
    ('wide' => true), alltså tillsammans med resten av sidans
    uppgifter.

    Övriga sidor är oförändrade, och det är ett val: en textspalt
    som är en meter bred går inte att läsa. */
.page--wide {
    --width-page: 100%;
}


/*  EN DEL MED EGEN MENY

    Administrationsdelen: vänsterspalt med delens sidor, innehållet
    till höger. Ramen som ritar den är layout/admin-head.php, och det
    är också DEN som gör sidan bred - bredden är en uppgift om delen
    och inte om var sida för sig.

    grid och inte flex: spalten ska ha ett fast mått medan innehållet
    tar resten. minmax(0, 1fr) är raden som gör att en bred tabell
    krymper inuti sin egen spalt i stället för att knuffa menyn ut ur
    fönstret - utan den är minsta bredden innehållets egen, och den
    kan vara vilken som helst. */
.admin {
    display: grid;
    grid-template-columns: 13rem minmax(0, 1fr);
    gap: var(--space-6);
    align-items: start;
}

/*  Menyn.

    sticky gör att den följer med när man läser en logg med tusen
    rader. Den fungerar bara tack vare align-items: start ovanför -
    en spalt som sträcks ut till hela höjden har ingenting att glida
    inom. */
.admin__nav {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);

    position: sticky;
    top: var(--space-4);
}

/*  Rubriken ÄR vägen tillbaka till delens översikt, se
    admin-head.php. Den ser ut som en etikett och inte som ett val,
    därför att den inte är ett av valen. */
.admin__title {
    margin-bottom: var(--space-2);
    padding: var(--space-2) var(--space-3);

    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.admin__title:hover,
.admin__title.is-current {
    color: var(--color-heading);
    text-decoration: none;
}

.admin__link {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);

    font-size: var(--text-sm);
    color: var(--color-text-muted);

    transition: background var(--transition), color var(--transition);
}

.admin__link:hover {
    color: var(--color-heading);
    background: var(--color-surface-hover);
    text-decoration: none;
}

.admin__link.is-current {
    color: var(--color-heading);
    background: var(--color-surface-strong);
}

/*  Innehållet staplas som på en vanlig sida - .site-main gör samma
    sak, men den är förälder till spalten och inte till innehållet. */
.admin__content {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}


/*  MENYKNAPPEN

    Fäller ut menyvalen på smala skärmar, och göms på breda. HELA
    växlingen ligger i avsnitt 5 - allt nedan är knappens utseende.

    Markeringen är en <details> och det är WEBBLÄSAREN som fäller
    ut den, precis som profilknappen. Ingenting nedan får
    utfällningen att fungera.

    MENYN LIGGER INTE INUTI DEN utan som syskon efter, och det är
    ingenting att "städa upp" - skälet står i rutan i
    layout/header.php. */

.menu {
    /*  Ritas först under menyns brytpunkt, se avsnitt 5 */
    display: none;

    flex: 0 0 auto;
}

/*  Knappen.

    Kvadratisk och inte textbred: den innehåller bara en ikon, och
    en tumme behöver en yta att träffa. */
.menu__toggle {
    display: flex;
    align-items: center;
    justify-content: center;

    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-md);

    color: var(--color-text-muted);

    cursor: pointer;
    user-select: none;

    /*  Två rader för samma sak, och båda behövs: den ena tar bort
        triangeln i de webbläsare som ritar den som en listpunkt,
        den andra i de som ritar den som ett eget element. Tas den
        ena bort kommer triangeln tillbaka i hälften av dem. */
    list-style: none;

    transition: background var(--transition), color var(--transition);
}

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

.menu__toggle:hover,
.menu[open] .menu__toggle {
    color: var(--color-heading);
    background: var(--color-surface-hover);
}

/*  Utan den här raden får knappen webbläsarens egen fokusmarkering,
    som är osynlig mot mörkt tema i vissa av dem. */
.menu__toggle:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}

/*  Ikonen: tre streck, ritade och inte skrivna.

    Mittenstrecket är elementet självt, de yttre är dess ::before
    och ::after - alltså ett enda tomt span i märkningen. Ett
    tecken i texten hade lästs upp för den som lyssnar, och knappen
    heter inte "tre streck"; namnet står i aria-label. */
.menu__icon,
.menu__icon::before,
.menu__icon::after {
    display: block;
    width: 1.125rem;
    height: 2px;
    border-radius: 1px;

    background: currentColor;

    transition: transform var(--transition), background var(--transition), top var(--transition);
}

.menu__icon {
    position: relative;
}

.menu__icon::before,
.menu__icon::after {
    content: "";
    position: absolute;
    left: 0;
}

.menu__icon::before {
    top: -0.375rem;
}

.menu__icon::after {
    top: 0.375rem;
}

/*  Utfälld blir strecken ett kryss: mittenstrecket försvinner och
    de yttre läggs ovanpå varandra, vridna åt var sitt håll.

    Mittenstrecket tas bort med background och inte med visibility
    eller display - dess ::before och ::after ÄR de två andra
    strecken, och de skulle följa med. */
.menu[open] .menu__icon {
    background: transparent;
}

.menu[open] .menu__icon::before {
    top: 0;
    transform: rotate(45deg);
}

.menu[open] .menu__icon::after {
    top: 0;
    transform: rotate(-45deg);
}


/*  LOGOTYPEN

    margin-right: auto ÄR högerställningen på hela toppraden. Allt
    ledigt utrymme samlas direkt efter logotypen, alltså hamnar
    både menyvalen och besökarens del vid högerkanten - med
    toppradens gap emellan.

    RADEN LIGGER HÄR OCH INTE PÅ DET SOM SKA STÅ TILL HÖGER, och
    det är hela poängen: den fungerar likadant oavsett VAD som
    kommer efter. Menyvalen kan vara gömda bakom menyknappen, och
    en sajt utan menyval ritar ingen <nav> alls - i båda fallen
    hamnar profilknappen ändå längst ut. Läggs raden i stället på
    två element får de ett halvt tomrum var, och menyn glider in
    mot mitten. */
.brand {
    margin-right: auto;

    display: flex;
    align-items: center;
    gap: var(--space-3);

    color: var(--color-heading);
    text-decoration: none;
}

.brand:hover {
    color: var(--color-heading);
    text-decoration: none;
}

/*  Märket är bilden i SITE_LOGO (config.php).

    MÅTTET STÅR HÄR OCH FILEN DÄR. Bilden ritas i det mått som står
    nedan oavsett hur stor filen är, alltså går en logotyp att byta
    utan att någon behöver skala om den först.

    Ingen bakgrund och ingen rundning: logotypen bär sin egen form,
    och en färgad ruta bakom en genomskinlig bild syns som en ruta.

    contain och inte cover - en logotyp som inte är kvadratisk ska
    krympa, inte beskäras. */
.brand__mark {
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;

    object-fit: contain;
}

.brand__text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.brand__name {
    font-weight: 600;
    font-size: var(--text-lg);
}

.brand__tagline {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}


/*  MENYN */
.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.site-nav__link {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);

    font-size: var(--text-sm);
    color: var(--color-text-muted);

    transition: background var(--transition), color var(--transition);
}

.site-nav__link:hover {
    color: var(--color-heading);
    background: var(--color-surface-hover);
    text-decoration: none;
}

/*  Sidan man står på. Markeringen är en bakgrund och inte fetstil -
    fetstil skulle ändra textens bredd och få menyn att hoppa när
    man byter sida. */
.site-nav__link.is-current {
    color: var(--color-heading);
    background: var(--color-surface-strong);
}

/*  BESÖKARENS EGEN DEL

    Profilknappen eller Logga in, sist på raden.

    INGEN margin-left: auto här. Högerställningen sköts av .brand
    ovan, och en andra auto-marginal hade delat tomrummet mellan
    de två - menyvalen hade då hamnat mitt på raden i stället för
    bredvid knappen. Se rutan vid .brand. */
.site-header__account {
    flex: 0 0 auto;

    display: flex;
    align-items: center;
    gap: var(--space-2);
}


/*  PROFILKNAPPEN

    Kontots egna vägar, samlade under namnet i toppraden. Markeringen
    är en <details> och det är WEBBLÄSAREN som fäller ut den - allt
    nedan är utseende, ingenting av det får utfällningen att fungera.
    Se layout/header.php och assets/js/menu.js. */

.profile {
    /*  Rutan nedan placeras mot den här, och inte mot sidan. Utan
        raden hamnar den i fönstrets övre vänstra hörn. */
    position: relative;
}

/*  Knappen.

    EGEN PIL, till skillnad från .reveal som låter webbläsaren rita
    sin. Skillnaden är avsiktlig: det här är en knapp i sajtens
    topprad och ska se likadan ut i varje webbläsare, medan ett
    avsnitt man fäller ut inne på en sida tjänar på att bära den form
    besökaren känner igen från allt annat. */
.profile__button {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);

    font-size: var(--text-sm);
    color: var(--color-text-muted);

    cursor: pointer;
    user-select: none;

    /*  Två rader för samma sak, och båda behövs: den ena tar bort
        triangeln i de webbläsare som ritar den som en listpunkt, den
        andra i de som ritar den som ett eget element. Tas den ena
        bort kommer triangeln tillbaka i hälften av dem. */
    list-style: none;

    transition: background var(--transition), color var(--transition);
}

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

.profile__button:hover,
.profile[open] .profile__button {
    color: var(--color-heading);
    background: var(--color-surface-hover);
}

/*  Utan den här raden får knappen webbläsarens egen fokusmarkering,
    som är osynlig mot mörkt tema i vissa av dem. */
.profile__button:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}

/*  Namnet bryts inte. En knapp som blir två rader hög knuffar hela
    toppraden nedåt, och namnet är ändå kort nog att få plats. */
.profile__name {
    white-space: nowrap;
}

/*  Pilen: två kanter på en kvadrat som vridits ett halvt varv.

    Ritad och inte skriven, därför att ett tecken i texten skulle
    läsas upp för den som lyssnar - och "Krille nedåtpil" är inte
    vad knappen heter. */
.profile__arrow {
    width: 0.4rem;
    height: 0.4rem;
    flex: 0 0 auto;

    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;

    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--transition);
}

.profile[open] .profile__arrow {
    transform: translateY(1px) rotate(225deg);
}

/*  Rutan som fälls ut.

    ABSOLUT PLACERAD, och det är hela poängen. En meny som ligger i
    flödet knuffar sidan nedåt när den öppnas, alltså flyttar sig det
    man just skulle klicka på. right: 0 gör att den växer inåt i
    stället för ut genom fönsterkanten. */
.profile__menu {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    z-index: 20;

    min-width: 12rem;
    padding: var(--space-2);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);

    background: var(--color-surface);
}

.profile__links {
    display: flex;
    flex-direction: column;
}

/*  Valen.

    Länkarna och utloggningsknappen ser med flit likadana ut: de står
    i samma lista och ska läsas som samma sorts val, oavsett att det
    ena är en länk och det andra ett formulär. */
.profile__link {
    display: block;
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);

    font-size: var(--text-sm);
    text-align: left;
    color: var(--color-text);

    transition: background var(--transition), color var(--transition);
}

.profile__link:hover {
    color: var(--color-heading);
    background: var(--color-surface-hover);
    text-decoration: none;
}

/*  Sidan man står på. Bakgrund och inte fetstil, av samma skäl som
    i toppmenyn: fetstil ändrar textens bredd. */
.profile__link.is-current {
    color: var(--color-heading);
    background: var(--color-surface-strong);
}

/*  Utloggningen är en <button> i ett formulär och inte en länk, se
    rutan i header.php om varför. Raderna nedan tar bort knappens
    egen form så att den ser ut som valen ovanför. */
.profile__link--action {
    border: 0;
    font-family: inherit;
    background: transparent;
    cursor: pointer;
}

/*  Linjen skiljer det som GÖR något från det som går någonstans */
.profile__form {
    margin: var(--space-2) 0 0 0;
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border-soft);
}


/*------------------------------------------------------------------
//
//	4. Komponenter
//
------------------------------------------------------------------*/

/*  4.1 KNAPPAR
    -------------------------------------------------------------- */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);

    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);

    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: 500;
    line-height: 1.5;

    color: var(--color-heading);
    background: var(--color-surface);

    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.button:hover {
    background: var(--color-surface-hover);
    border-color: var(--color-border-strong);
    color: var(--color-heading);
    text-decoration: none;
}

/*  Knappen för det som är sidans egentliga syfte. EN sådan per
    sida - är allt framhävt är ingenting framhävt. */
.button--strong {
    color: var(--color-on-accent);
    background: var(--color-accent);
    border-color: var(--color-accent);
}

.button--strong:hover {
    color: var(--color-on-accent);
    background: var(--color-accent-hover);
    border-color: var(--color-accent-hover);
}

/*  Diskret variant, t.ex. utloggningsknappen i menyn */
.button--quiet {
    color: var(--color-text-muted);
    background: transparent;
    border-color: transparent;
}

.button--quiet:hover {
    color: var(--color-heading);
    background: var(--color-surface-hover);
    border-color: transparent;
}

/*  Det som tar bort eller stänger av något.

    Färgen är en VARNING och inte en dekoration - använd den bara
    när handlingen är svår att ångra. */
.button--danger {
    color: var(--color-danger);
    border-color: var(--color-danger-border);
    background: transparent;
}

.button--danger:hover {
    color: var(--color-on-danger);
    background: var(--color-danger);
    border-color: var(--color-danger);
}

/*  En avstängd knapp ska SE avstängd ut. Utan det här ser den ut
    som en knapp som inte fungerar, vilket är något helt annat. */
.button:disabled,
.button[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}


/*  4.2 MEDDELANDERUTOR
    --------------------------------------------------------------
    Skrivs ut av include/layout/flash.php, ett enda ställe.

    FÄRGEN ÄR INFORMATION HÄR, inte pynt. Ett tema utan färg på de
    fyra typerna gör att ett fel och en bekräftelse ser likadana
    ut - därför bär även gråskaletemat riktiga signalfärger. */

.flash-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.flash {
    margin: 0;
    max-width: none;
    padding: var(--space-3) var(--space-4);

    border: 1px solid var(--color-border);
    border-left-width: 4px;
    border-radius: var(--radius-md);

    background: var(--color-surface);
    font-size: var(--text-sm);
}

.flash--info    { border-left-color: var(--color-info);    }
.flash--success { border-left-color: var(--color-success); }
.flash--warning { border-left-color: var(--color-warning); }
.flash--error   { border-left-color: var(--color-danger);  }


/*  4.3 PANELER
    --------------------------------------------------------------
    Sidans grundbyggsten. En panel = ett ämne. */

.panel {
    padding: var(--space-5);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);

    background: var(--color-surface);
}

/*  Ett formulär med några fält. Se --width-narrow. */
.panel--narrow {
    width: 100%;
    max-width: var(--width-narrow);
    margin: 0 auto;
}

.panel--centered {
    text-align: center;
}

.panel--centered p,
.panel--centered .form__actions {
    max-width: none;
}

/*  EN PANEL SOM SKA LÄSAS, I EN DEL SOM ÄR BRED

    Administrationsdelen tar hela fönstret för tabellernas skull. En
    sida därinne som är löptext och uppgifter i stället för en tabell
    ska inte bli en meter bred bara därför.

    RUTAN BEHÅLLER HELA BREDDEN och bara innehållet kapas: alla rutor
    på en sida ska ha samma kant, annars ser sidan trasig ut. Och
    innehållet ligger kvar till VÄNSTER, inte centrerat - ögat letar
    efter radernas början på samma ställe hela vägen ned.

    Stycken är redan kapade vid 62 tecken av regeln för <p> i avsnitt
    2, som gäller överallt. Den här raden är för resten: listor,
    rubriker och tabeller. */
.panel--reading > * {
    max-width: var(--width-content);
}

/*  Det som är information snarare än handling. Tonas ned så att
    ögat hittar det som faktiskt ska göras. */
.panel--quiet {
    background: transparent;
    border-style: dashed;
}

.panel__heading {
    margin-bottom: var(--space-3);
}

/*  Rubrik för en avdelning inne i en panel */
.panel__section {
    margin-top: var(--space-5);
    margin-bottom: var(--space-2);
    font-size: var(--text-base);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
}

/*  Inledande text under en rubrik */
.panel__lead {
    color: var(--color-text-muted);
}

/*  Liten förklarande text, normalt längst ned i en panel */
.panel__note {
    margin-top: var(--space-4);
    margin-bottom: 0;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

/*  Avdelaren mellan två länkar på samma rad */
.panel__note-sep {
    padding: 0 var(--space-2);
    color: var(--color-text-faint);
}

/*  Text som MÅSTE läsas innan man går vidare.

    Inte samma sak som .panel__note: den är en fotnot, den här är en
    varning. Kanten till vänster är samma grepp som flash--warning
    använder, så att de två känns igen som samma sorts besked. */
.panel__warning {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);

    border-left: 3px solid var(--color-warning);
    border-radius: var(--radius-sm);

    background: var(--color-surface-strong);
    color: var(--color-heading);
}


/*  4.4 INLEDNINGEN PÅ STARTSIDAN
    -------------------------------------------------------------- */

.hero {
    padding: var(--space-6) 0 var(--space-2) 0;
    text-align: center;
}

.hero__heading {
    font-size: var(--text-3xl);
    margin-bottom: var(--space-4);
}

.hero__lead {
    margin: 0 auto;
    font-size: var(--text-lg);
    color: var(--color-text-muted);
}


/*  4.5 FORMULÄR
    -------------------------------------------------------------- */

.form {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    margin: 0;
}

/*  Ett formulär som bara är en knapp, t.ex. "avbryt" */
.form--inline {
    margin-top: var(--space-4);
}

/*  Ett fält = etikett, ruta och eventuell förklaring */
.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.field__label {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--color-heading);
}

.field__help {
    margin: 0;
    max-width: none;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

.input {
    width: 100%;
    padding: var(--space-3);

    border: 1px solid var(--color-input-border);
    border-radius: var(--radius-md);

    font-family: inherit;
    font-size: var(--text-base);

    color: var(--color-text);
    background: var(--color-input);

    transition: border-color var(--transition);
}

.input:hover {
    border-color: var(--color-border-strong);
}

/*  Ingen egen fokusmarkering - :focus-visible i avsnitt 2 gäller,
    och två markeringar ovanpå varandra ser ut som ett fel. */

/*  Ett flerradigt fält, i dag kontaktformulärets meddelande.
    Samma utseende som .input, plus en höjd att skriva i och ett
    handtag att dra i - textarea ärver annars ingenting av det. */
.input--textarea {
    min-height: 8rem;
    font-family: inherit;
    resize: vertical;
}

/*  En ruta som innehåller en kod och inte en mening. Monospace
    gör att siffrorna står rakt under varandra, och den extra
    teckenavståndet gör att man ser var man är när man skriver av
    sex siffror. */
.input--code {
    font-family: var(--font-mono);
    font-size: var(--text-xl);
    letter-spacing: 0.4em;
    text-align: center;
}

.form__actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin: 0;
    max-width: none;
}

/*  EN KNAPPRAD SOM INTE STÅR I ETT FORMULÄR

    Inne i .form är det gap:et som håller isär raderna, och då ska
    knappraden inte lägga till något eget - därför margin: 0 ovan.

    Men knappraden används också rakt i en panel: under en
    <dl class="data-list">, under en .panel__note. Båda har
    bottenmarginal 0, och då står knappen klistrad mot texten
    ovanför.

    Marginalen läggs bara när det FINNS ett syskon ovanför, och den
    faller samman med syskonets bottenmarginal - en knapprad efter
    ett vanligt stycke står alltså kvar precis där den stod. */
.panel > * + .form__actions {
    margin-top: var(--space-4);
}

/*  BETET MOT ROBOTAR, se class/Honeypot.php.

    display:none hade dolt fältet för EN SKÄRMLÄSARE OCKSÅ - precis
    den grupp av besökare som mest riskerar att fylla i varje fält
    de kan nå. Fältet ligger i stället kvar i sidans flöde men
    utanför skärmens kant, och aria-hidden i markeringen tar bort
    det ur skärmläsarens träd helt. Ett skript som bara läser
    HTML:en ser ett vanligt fält, oavsett vilket. */
.field-trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}


/*  4.6 UPPGIFTER I TVÅ SPALTER
    --------------------------------------------------------------
    En <dl> där etiketten står till vänster och värdet till höger. */

.data-list {
    display: grid;
    grid-template-columns: minmax(8rem, 14rem) 1fr;
    gap: var(--space-2) var(--space-4);
    margin: 0;
}

/*  Samma lista i en SMAL SPALT, i dag uppgifterna i kontolistans
    utfällning.

    Måttet ovan är tilltaget för en hel sida: etiketten tar 14 rem så
    fort det finns plats, och står listan i en spalt som delar
    bredden med något annat blir det under tio tecken kvar åt värdet
    - alltså bröts e-postadressen mitt itu.

    HÄR FÅR ETIKETTEN BARA DET DEN BEHÖVER. max-content är den
    längsta etiketten i den här listan och inte ett mått taget på
    måfå, alltså stämmer det även på ett språk där etiketterna är
    längre. Resten går till värdet, som är det man kom för att läsa.

    EGEN KLASS OCH INTE ".detail .data-list". En sådan regel väger
    tyngre än den som staplar listan på en telefon (avsnitt 5), och
    hade alltså tvingat kvar två spalter just där de inte får plats. */
.data-list--tight {
    grid-template-columns: minmax(6rem, max-content) 1fr;
}

.data-list dt {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

.data-list dd {
    margin: 0;
    color: var(--color-heading);
    /*  Ett långt värde utan mellanslag (ett id, en adress) ska
        brytas i stället för att tvinga fram en sidledsscroll. */
    overflow-wrap: anywhere;
}


/*  4.7 EN HEMLIGHET SOM SKA SKRIVAS AV
    --------------------------------------------------------------
    MFA-hemligheten på aktiveringssidan. Monospace och luft mellan
    grupperna, så att den går att skriva av utan att tappa
    räkningen - och markerbar, så att den går att kopiera. */

.secret-key {
    margin: var(--space-3) 0;
    padding: var(--space-4);

    border: 1px dashed var(--color-border-strong);
    border-radius: var(--radius-md);

    font-family: var(--font-mono);
    font-size: var(--text-lg);
    letter-spacing: 0.1em;
    text-align: center;
    word-break: break-all;

    color: var(--color-heading);
    background: var(--color-surface-strong);

    max-width: none;
    user-select: all;
}


/*  4.8 QR-KODEN
    --------------------------------------------------------------
    Bilden på aktiveringssidan. Ritas av class/QrCode.php som en
    svg i modulkoordinater, alltså sätts storleken HÄR och skalar
    utan att bli suddig.

    Måtten är inte godtyckliga: en telefonkamera vill ha ungefär
    två millimeter per modul, och en version 8-kod har 49 moduler.
    16rem på en vanlig skärm landar strax över det, och max-width
    hindrar att den blir bredare än en smal telefon.

    Färgerna står i svg:n och inte här - en QR-kod måste vara mörk
    på ljust för att gå att läsa, i varje tema. Rutan runt bilden
    är däremot vit även i mörkt tema av samma skäl: den vita ramen
    ÄR den tysta zonen, och utan ljust runt koden hittar läsaren
    inte kanten. */

.qr-code {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);

    margin: var(--space-3) 0;
}

.qr-code__image {
    display: block;

    width: 16rem;
    max-width: 100%;
    height: auto;

    border-radius: var(--radius-md);
}

.qr-code__caption {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    text-align: center;
}


/*  4.9 ÅTERSTÄLLNINGSKODER
    --------------------------------------------------------------
    Listan som visas EN gång när flerfaktorn slås på. Två spalter så
    att tio koder får plats utan att sidan blir en rulle, och samma
    monospace som hemligheten ovanför - de ska skrivas av för hand.

    user-select: all på varje kod gör att ett klick markerar hela
    koden och inte ett halvt tecken. */

.recovery-codes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--space-2);

    margin: var(--space-3) 0;
    padding: 0;
    list-style: none;

    max-width: none;
}

.recovery-codes__item {
    padding: var(--space-2) var(--space-3);

    border: 1px dashed var(--color-border-strong);
    border-radius: var(--radius-md);

    font-family: var(--font-mono);
    letter-spacing: 0.06em;
    text-align: center;

    color: var(--color-heading);
    background: var(--color-surface-strong);

    user-select: all;
}


/*  4.10 ETT AVSNITT MAN FÄLLER UT
    --------------------------------------------------------------
    <details> för det som ska finnas men inte stå i vägen - i mallen
    rutan för en återställningskod på kodsidan.

    Pilen är webbläsarens egen och ritas inte om: den ser olika ut i
    olika webbläsare, och det är rätt - besökaren känner igen sin
    egen. */

.reveal {
    margin-top: var(--space-5);
    border-top: 1px solid var(--color-border);
    padding-top: var(--space-4);
}

.reveal__summary {
    cursor: pointer;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

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

/*  Utan den här raden får sammanfattningen webbläsarens egen
    fokusmarkering, som är osynlig mot mörkt tema i vissa av dem. */
.reveal__summary:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}

/*  EN PANEL SOM ÄR SIN EGEN UTFÄLLNING

    Rutan innehåller ingenting annat än rubriken och det som fälls
    ut - i mallen formuläret som skapar ett konto på kontolistan.
    Strecket och avståndet ovanför hör till den lilla fotnotsvarianten
    och ska inte finnas här: panelens egen kant är redan avdelaren. */
.reveal--panel {
    margin-top: 0;
    border-top: 0;
    padding-top: 0;
}

/*  Rubriken ligger inne i <summary> för att avsnittet ska ha en
    riktig rubrik för den som lyssnar. Den ritas inline så att den
    står på samma rad som webbläsarens pil i stället för att bryta
    ned sig under den, och marginalen bort eftersom avståndet till
    det som fälls ut sätts av .reveal__body. */
.reveal--panel .panel__heading {
    display: inline;
    margin: 0;
}

.reveal__body {
    margin-top: var(--space-4);
}


/*  4.11 VAL I SIDFOTEN (språk, tema)
    -------------------------------------------------------------- */

.choice {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.choice__label {
    color: var(--color-text-faint);
}

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

.choice__option.is-current {
    color: var(--color-heading);
    font-weight: 600;
    text-decoration: underline;
}


/*  4.12 EN TABELL
    --------------------------------------------------------------
    Enkel och avskalad. Behöver sajten en tabell med frysta
    rubriker och tjugo kolumner är det en egen komponent, inte en
    utbyggnad av den här. */

.table-frame {
    /*  Tabellen scrollar i SIDLED inne i sin egen ruta. Utan det
        här får hela sidan en vågrät scroll, och då försvinner
        menyn ur bild när man tittar på den sista kolumnen. */
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
}

.table th,
.table td {
    padding: var(--space-2) var(--space-3);
    text-align: left;
    border-bottom: 1px solid var(--color-border-soft);
    white-space: nowrap;
}

.table th {
    font-weight: 600;
    color: var(--color-text-muted);
    background: var(--color-surface-strong);
}

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

/*  Tal ställs till höger. Siffror som ska jämföras med varandra
    måste stå under varandra. */
.table .is-number {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/*  Raden pekaren står på markeras.

    MODIFIERARE OCH INTE GRUNDFORM: en markering som följer pekaren
    säger "den här raden är den du håller på med", och det behövs
    först när raden har något att göra med - en knapp i sista
    kolumnen, eller många kolumner att följa med ögat.

    SKILJ DEN FRÅN .row I 4.21, som ser likadan ut men betyder något
    annat: den raden går att KLICKA på, och sätter därför pekaren
    till en hand. Här går bara knapparna att trycka på. */
.table--hover tbody tr:hover td {
    background: var(--color-surface-hover);
}

/*  Flera knappar i samma cell ligger på RAD och inte under
    varandra.

    Varje knapp är sitt eget formulär - en mottagare gör en sak -
    och ett formulär är en blockruta, alltså skulle knapparna annars
    stapla sig och göra tabellraden dubbelt så hög. */
.table-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}


/*  4.13 ETT MÄRKE
    --------------------------------------------------------------
    Ett kort ord som säger ett läge: "Aktiv", "Avstängd". */

.badge {
    display: inline-block;
    padding: var(--space-1) var(--space-2);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);

    font-size: var(--text-xs);
    line-height: 1.4;

    color: var(--color-text-muted);
    background: var(--color-surface-strong);
}

.badge--success { color: var(--color-success); border-color: var(--color-success); }
.badge--warning { color: var(--color-warning); border-color: var(--color-warning); }
.badge--danger  { color: var(--color-danger);  border-color: var(--color-danger);  }


/*  4.14 EN FILTERRAD
    --------------------------------------------------------------
    Fälten som avgör VAD en tabell visar, på en rad ovanför den.

    Fälten står bredvid varandra och inte under: ett filter är
    inte ett formulär man fyller i uppifrån och ner, det är några
    val man ändrar ett i taget. Radbrytningen sköter sig själv när
    fönstret blir smalt - därför inget eget mått för små skärmar. */

.filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-3);

    /*  Luft åt BÅDA hållen, och mer under än över. Raden och
        tabellen står i samma ruta - utan marginalen under klistrar
        rutorna i tabellens rubrikrad, och de två läses då som en
        enda klump i stället för som ett val och dess svar. */
    margin-top: var(--space-4);
    margin-bottom: var(--space-5);
}

/*  Varje fält får växa men aldrig bli smalare än så här. Under
    12rem ryms varken ett datum eller ett läsbart loggnamn. */
.filter-bar .field {
    flex: 1 1 12rem;
}

/*  LÄGG INGEN .field__help I EN FILTERRAD.

    Raden bottenjusterar sina fält (align-items ovan), och ett fält
    med en extra textrad under rutan blir högre än de andra - alltså
    lyfts just den rutan uppåt och rutorna står i trappa.

    Det som behöver sägas skrivs i etiketten i stället: "Sök på namn,
    e-post eller id" är både kortare och alltid synligt, till skillnad
    från en platshållartext som försvinner så fort man skriver. */

/*  Knapparna växer inte - de ska stå kvar vid radens slut och
    inte breda ut sig över det utrymme fälten lämnar. */
.filter-bar .form__actions {
    flex: 0 0 auto;
}

/*  En <select> ritas med .input och ska då se ut som ett fält.

    Pilen är webbläsarens egen och ritas inte om, av samma skäl
    som <details> behåller sin: den ser olika ut i olika
    webbläsare, och det är rätt - besökaren känner igen sin egen. */
select.input {
    /*  Ett fält är lika högt som ett annat. Utan raden blir
        <select> någon pixel lägre än <input> i de flesta
        webbläsare, och en filterrad där fälten står i trappa ser
        ut som ett fel. */
    line-height: 1.5;
}


/*  4.15 SIDINDELNING
    --------------------------------------------------------------
    Vägen till nästa knippe rader under en lång tabell.

    INGA SIDNUMMER, med flit. Numren skulle kräva att raderna
    räknas, och komponenten finns för tabeller som är för stora
    för just det - se Log::search() i class/Log.php. */

.pager {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-4);
}


/*  4.16 ETT KOMMANDO SOM SKA KOPIERAS
    --------------------------------------------------------------
    En SQL-sats eller en rad att klistra in i ett skal.

    INTE .secret-key: den är centrerad och glesad för att kunna
    SKRIVAS AV för hand, vilket är precis fel för något som ska
    markeras och kopieras.

    RULLAR I SIDLED i stället för att bryta raden. En lång sökväg
    eller ett GRANT som brutits på mitten går inte att klistra in,
    och den som kopierar märker det först när kommandot vägrar
    köra.

    user-select: all gör att ett klick markerar hela blocket - så
    hör också bara EN sats hemma i varje. */

.code-block {
    margin: var(--space-3) 0;
    padding: var(--space-3) var(--space-4);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);

    font-family: var(--font-mono);
    font-size: var(--text-sm);
    line-height: 1.5;
    white-space: pre;
    overflow-x: auto;

    color: var(--color-heading);
    background: var(--color-surface-strong);

    user-select: all;
}


/*  4.17 RUTOR SOM LEDER VIDARE
    --------------------------------------------------------------
    En ruta per sida på en dels framsida - i mallen /admin/.

    HELA RUTAN ÄR LÄNKEN och inte bara rubriken i den. En klickyta
    på tre ord mitt inne i en ruta är en klickyta man missar, och en
    ruta som ser ut att gå att trycka på ska gå att trycka på. */

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: var(--space-4);
}

.card {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);

    padding: var(--space-5);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);

    color: var(--color-text);
    background: var(--color-surface);

    transition: border-color var(--transition), background var(--transition);
}

.card:hover {
    border-color: var(--color-border-strong);
    background: var(--color-surface-hover);
    text-decoration: none;
}

.card__heading {
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--color-heading);
}

.card__text {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}


/*  4.18 SYNLIG FÖR DEN SOM LYSSNAR, OSYNLIG FÖR DEN SOM TITTAR
    --------------------------------------------------------------
    För text som en skärmläsare behöver men som skulle vara i
    vägen på skärmen. display:none skulle dölja den för BÅDA. */

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/*  4.19 RUTAN SOM FÄLLS UT
    --------------------------------------------------------------
    Inloggningen, öppnad från knappen i toppraden. Markeringen är en
    <dialog> och all form nedan gäller BARA när den öppnats med
    showModal() - en stängd dialog är display:none och syns inte.

    Behövs en andra ruta någon gång är .modal generell: ingenting
    nedan vet något om inloggningen, och id:t signin-dialog används
    bara av markeringen och av skriptet. */

.modal {
    /*  Webbläsarens egen dialogform bort. Panelen innanför bär allt
        utseende, och det är den som ska gå att känna igen som en
        panel bland andra. */
    padding: 0;
    border: 0;
    background: transparent;

    /*  Bredden är formulärets, inte fönstrets. Samma mått som en
        smal panel, så att rutan och sidan /sign-in/ ser lika ut.

        MARGINALEN I width ÄR INTE UTBYTBAR MOT margin. En modal
        <dialog> centreras av webbläsarens egen "margin: auto", och
        skriver man över den försvinner centreringen. Att i stället
        låta bredden lämna plats gör att rutan aldrig ligger kant i
        kant med skärmen på en telefon - och centreringen är kvar. */
    width: calc(100% - var(--space-4) * 2);
    max-width: var(--width-narrow);

    /*  max-height och overflow: ett formulär som inte får plats på
        en låg skärm ska gå att rulla i, inte klippas av. */
    max-height: 90dvh;
    overflow-y: auto;

    color: var(--color-text);
}

/*  Bakgrunden bakom rutan. Mörkläggningen är en egen variabel och
    inte en opacity på något: en genomskinlig svart yta ser olika ut
    i ljust och mörkt tema, och ska därför bestämmas av temat. */
.modal::backdrop {
    background: var(--color-backdrop);
}

/*  Själva panelen. Samma form som .panel - avsiktligt, en ruta är
    inte en egen sorts yta utan en panel som ligger ovanpå. */
.modal__panel {
    position: relative;
    padding: var(--space-5);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);

    background: var(--color-surface);
}

.modal__heading {
    margin-bottom: var(--space-4);

    /*  Plats för krysset, så att en lång rubrik inte hamnar under
        det. */
    padding-right: var(--space-6);
}

/*  Krysset.

    Ligger i hörnet och inte i ett eget fält: rutan är liten, och en
    rad bara för en stängknapp skulle ta en fjärdedel av den. */
.modal__close {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);

    /*  Träffytan är större än tecknet. Ett kryss som är exakt så
        stort som glyfen är svårt att träffa med tummen. */
    width: 2.25rem;
    height: 2.25rem;

    display: flex;
    align-items: center;
    justify-content: center;

    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);

    font-size: var(--text-xl);
    line-height: 1;

    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
}

.modal__close:hover {
    background: var(--color-surface-hover);
    color: var(--color-heading);
}


/*  4.20 EN KRYSSLISTA
    --------------------------------------------------------------
    Flera val som INTE utesluter varandra - i mallen rollerna ett
    nytt konto ska få. Är valen ömsesidigt uteslutande är det en
    <select> eller radioknappar, inte den här.

    Rutan och texten ligger i samma <label>, alltså är hela plattan
    klickbar och inte bara den lilla rutan. Det är skillnaden som
    märks på en telefon. */

.check-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--space-2);

    margin: 0;
    padding: 0;
    list-style: none;

    max-width: none;
}

/*  PLATTORNA I EN RAD SKA VARA LIKA HÖGA, även när en roll saknar
    beskrivning och en annan har två rader. Den kortaste ser annars
    ut som något annat än de andra i stället för som samma sorts val.

    Rutnätet sträcker <li> till radens höjd; flexraden härinne är det
    som får plattan att fylla den. */
.check-list > li {
    display: flex;
}

.check {
    flex: 1;

    /*  Två spalter: rutan och texten. Beskrivningen läggs på egen
        rad under namnet men i textens spalt, se .check__desc. */
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-1) var(--space-3);
    align-items: start;

    padding: var(--space-3);

    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);

    cursor: pointer;
    transition: border-color var(--transition);
}

.check:hover {
    border-color: var(--color-border-strong);
}

/*  MÅTTET STÅR HÄR för att en kryssruta ärver varken teckenstorlek
    eller typsnitt av sin omgivning. Utan raden blir rutan olika stor
    i olika webbläsare, och plattorna olika höga bredvid varandra. */
.check__input {
    width: 1rem;
    height: 1rem;
    margin: 0;

    /*  Färgen på krysset när rutan är ifylld. Webbläsaren ritar
        resten - en egen kryssruta byggd av divar tappar tangentbordet
        och skärmläsaren, och vinner ingenting. */
    accent-color: var(--color-accent);
}

.check__name {
    font-weight: 500;
    color: var(--color-heading);
}

/*  Spalt 2 och inte automatisk placering: beskrivningen ska stå
    under namnet, i linje med det, och inte under kryssrutan. */
.check__desc {
    grid-column: 2;

    margin: 0;
    max-width: none;

    font-size: var(--text-xs);
    color: var(--color-text-muted);
}


/*  4.21 EN RAD SOM FÄLLS UT
    --------------------------------------------------------------
    Kontolistan: ett klick på en rad visar mer om kontot i en rad
    under den. Formen nedan gäller BÅDA vägarna dit - den som ritas
    av servern på ?open= och den som hämtas i bakgrunden - eftersom
    de lämnar exakt samma markering efter sig.

    LIGGER I 4.21 OCH INTE I 4.12 (tabellen). Tabellen är en form
    vilken sida som helst kan använda; det här är en komponent som
    bygger på den. Den som vill ha en vanlig tabell ska slippa läsa
    trettio rader om utfällningar. */

/*  Hela raden tar emot klicket, alltså ska den se ut att göra det.
    Pekaren är den enda signal som finns innan man klickat. */
.row {
    cursor: pointer;
}

.row:hover td,
.row.is-open td {
    background: var(--color-surface-hover);
}

/*  Pilens kolumn ska vara precis så bred som pilen. Ett litet mått
    räcker: en tabellcell kan ändå inte bli smalare än sitt
    innehåll. */
.row__toggle {
    width: 1px;
}

.toggle {
    display: flex;
    align-items: center;
    justify-content: center;

    width: 1.75rem;
    height: 1.75rem;

    border-radius: var(--radius-sm);

    color: var(--color-text-muted);
    text-decoration: none;
}

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

/*  Pilen: två kanter på en kvadrat som vridits ett kvarts varv.
    Samma grepp som profilknappens pil i avsnitt 3, och av samma
    skäl - en bild till för ett vinkeltecken är en fil till att
    hämta, och ett tecken ur typsnittet ser olika ut i olika
    webbläsare.

    RITAD OCH INTE SKRIVEN betyder också att den kan vridas mjukt
    när raden öppnas, vilket är det som gör att man förstår att den
    hör ihop med det som fälldes ut. */
.toggle__mark {
    width: 0.45rem;
    height: 0.45rem;

    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;

    /*  Ihopfälld pekar den åt höger: "det finns mer den vägen". */
    transform: rotate(-45deg);
    transition: transform var(--transition);
}

/*  Utfälld pekar den nedåt, mot det som kom fram. LÄGET LÄSES UR
    aria-expanded och inte ur en egen klass: attributet måste ändå
    hållas rätt för den som lyssnar, och två sanningar om samma sak
    är en som glöms. */
[aria-expanded="true"] .toggle__mark {
    transform: rotate(45deg);
}

/*  Raden som innehåller utfällningen.

    Cellen har ingen egen luft - den ligger i .row-detail__slot
    i stället, så att en tom utfällning inte blir en rad tomrum
    medan innehållet hämtas. */
.row-detail > td {
    padding: 0;
    background: var(--color-surface-strong);
}

/*  Sista raden i tabellen saknar understrykning (se 4.12), och med
    utfällningsrader är den sista raden alltid en sådan - dold eller
    inte. Är den dold ligger strecket kvar under den sista SYNLIGA
    raden, mitt i ramens nederkant.

    :has() saknas i riktigt gamla webbläsare. Där blir följden ett
    hårstreck för mycket längst ned, och ingenting annat. */
.table tr:has(+ .row-detail[hidden]:last-child) > td {
    border-bottom: none;
}

.row-detail__slot {
    padding: var(--space-4);

    /*  Tabellceller är nowrap (se 4.12) för att kolumnerna ska stå
        still. Härinne är innehållet text och formulär, och det ska
        brytas som text gör. */
    white-space: normal;
}

/*  Delarna i utfällningen: uppgifter, ändringsformulär, logg.

    DELARNA LÄGGER OM SIG SJÄLVA. De är två eller tre i dag och kan
    bli fler - se rutan om att bygga vidare i
    layout/account-detail.php. Var och en tar en andel av bredden så
    länge den får sitt minsta mått, och lägger sig på egen rad när
    den inte gör det.

    FLEX OCH INTE ETT RUTNÄT MED auto-fit. Rutnätet gör samma sak
    ända tills en del spänner över alla spalter, som loggen gör
    nedan: en spalt som något spänner över räknas inte som tom,
    alltså föll auto-fit:s hopfällning av tomma spalter bort. Kvar
    blev tre lika breda spalter där två var ifyllda och den tredje
    stod tom längst till höger - och uppgiftslistan fick en tredjedel
    av bredden i stället för hälften. */
.detail {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
    align-items: start;
}

.detail__part {
    /*  Delar lika på bredden, men aldrig smalare än ett
        formulärfält med sin etikett - då bryts raden i stället. */
    flex: 1 1 24rem;

    /*  UTAN DEN HÄR RADEN SPRÄNGER EN TABELL SIN DEL. En flexruta
        får som minst vara så bred som sitt innehåll, och en tabell
        med tio kolumner är bred. min-width: 0 säger att den får
        vara smalare - och då tar .table-frame över med sin egen
        scroll, vilket är precis vad den finns till för. */
    min-width: 0;
}

/*  En del som ska ha hela bredden för sig själv, i dag loggen. En
    tabell i en halv spalt blir en tabell med vågrät scroll. */
.detail__part--wide {
    flex-basis: 100%;
}

.detail__heading {
    margin-bottom: var(--space-3);

    font-size: var(--text-base);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
}


/*------------------------------------------------------------------
//
//	5. Mindre skärmar
//
//  Sajten är byggd smal först i den meningen att ingenting har en
//  fast bredd i pixlar. Det som behövs här är bara att lägga om
//  det som står bredvid varandra.
//
//  TVÅ BRYTPUNKTER, OCH DE MÄTER OLIKA SAKER:
//
//    48rem  Menyn. När toppradens val inte längre får plats
//           bredvid logotypen och vägen in.
//    40rem  Sidan. När två spalter inte längre får plats bredvid
//           varandra.
//
//  Menyns kommer först därför att den slår till tidigare: en meny
//  med sex val fyller toppraden långt innan innehållet under den
//  behöver läggas om. Ordningen i filen är också den ordning som
//  gäller - reglerna för 40rem läses sist och vinner därför när
//  båda frågorna svarar ja.
//
------------------------------------------------------------------*/

/*  MENYNS BRYTPUNKT
    --------------------------------------------------------------

    VÄRDET GÅR INTE ATT LÄGGA I EN VARIABEL. En @media-fråga kan
    inte läsa var(--...), alltså står talet skrivet. Ska menyn
    fällas ihop vid en annan bredd ändras det HÄR, på ett ställe -
    leta inte efter en variabel som inte finns. */
@media (max-width: 48rem) {

    /*  Knappen fram, valen bort. */
    .menu {
        display: block;
    }

    .site-nav {
        display: none;
    }

    /*  Den utfällda menyn.

        SYSKONVÄLJARE och inte en regel på <details>-kroppen: <nav>
        ligger UTANFÖR sin <details>, och skälet står i rutan i
        layout/header.php.

        ABSOLUT PLACERAD, av samma skäl som profilmenyn: en meny som
        ligger i flödet knuffar sidan nedåt när den öppnas, alltså
        flyttar sig det man just skulle trycka på. left och right i
        stället för en bredd gör att rutan följer toppradens indrag
        - --header-inset ärvs från .site-header och är samma mått
        som radens egen padding, så valen hamnar i linje med
        logotypen ovanför. */
    .menu[open] ~ .site-nav {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-1);

        position: absolute;
        top: 100%;
        left: var(--header-inset);
        right: var(--header-inset);
        z-index: 20;

        padding: var(--space-2);

        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);

        background: var(--color-surface);
    }

    /*  Valen fyller rutans bredd och blir högre. En länk som är
        klickbar bara där texten råkar sluta är svår att träffa
        med en tumme. */
    .menu[open] ~ .site-nav .site-nav__link {
        padding: var(--space-3);
        font-size: var(--text-base);
    }

    /*  Undertexten under sajtens namn tas bort.

        Den är en trevlighet på en bred skärm och en bortkastad rad
        höjd på en telefon - och höjden behövs till knappen,
        logotypen och vägen in, som alla ska rymmas på samma rad. */
    .brand__tagline {
        display: none;
    }

    /*  TOPPRADEN BRYTS INTE, hur lång texten än är.

        Utan raden är ett långt visningsnamn nog för att besökarens
        del ska hamna på en andra rad - och en topprad som är dubbelt
        så hög på ett konto och inte på ett annat är inte en topprad
        man litar på. Det som ska ge vika är TEXTEN, och den ger
        vika nedan. */
    .site-header {
        flex-wrap: nowrap;
    }

    /*  VEM SOM KRYMPER FÖRST, och varför det inte är samma sak för
        de två.

        Sajtens namn är ett val någon gjort en gång och kan hållas
        kort. Visningsnamnet är något besökaren skrivit in, och det
        kan vara hur långt som helst - alltså är det den texten som
        ska kapas först. Talet 3 är precis det: besökarens del ger
        vika tre gånger så fort som logotypen gör.

        min-width: 0 på båda är det som över huvud taget TILLÅTER
        dem att krympa. En flexruta vägrar som standard bli smalare
        än sitt innehåll, och utan raden svämmar raden i stället
        över kanten. */
    .brand {
        min-width: 0;
    }

    .site-header__account {
        min-width: 0;
        flex-shrink: 3;
    }

    /*  Kedjan ned till texten.

        Varje ruta mellan flexraden och den text som ska kapas måste
        släppa igenom krympningen. Missas ett steg tar kapningen
        aldrig vid, och raden svämmar över i stället - det syns bara
        på ett långt namn, alltså i just det läge regeln finns för. */
    .profile,
    .profile__button {
        min-width: 0;
    }

    /*  Namnet kapas med tre punkter.

        white-space: nowrap står redan på .profile__name längre upp,
        och alla tre behövs: utan nowrap bryts texten i stället för
        att kapas, utan overflow syns den utanför sin ruta, och utan
        display: block har text-overflow ingen ruta att arbeta i. */
    .profile__name {
        display: block;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}


/*  SIDANS BRYTPUNKT
    -------------------------------------------------------------- */
@media (max-width: 40rem) {

    /*  Toppraden blir INTE en kolumn. Den ska rymma menyknappen,
        logotypen och vägen in på en och samma rad ända ned till
        den smalaste telefonen - undertexten är borta sedan 48rem
        och det är den som tar plats. Räcker bredden ändå inte
        faller besökarens del ned på en andra rad av sig själv,
        vilket flex-wrap ovan redan sköter. */
    .site-header {
        --header-inset: var(--space-4);

        padding: var(--header-inset);
    }

    .site-main {
        padding: var(--space-3) var(--space-4) var(--space-7) var(--space-4);
    }

    .site-footer {
        padding: var(--space-4);
        flex-direction: column;
        align-items: flex-start;
    }

    .panel {
        padding: var(--space-4);
    }

    /*  Vänsterspalten blir en rad ovanför innehållet.

        En meny på 13 rem bredvid en tabell lämnar ingenting kvar åt
        tabellen på en telefon - och tabellen är skälet till att
        delen är bred över huvud taget.

        MINMAX(0, 1FR) OCH ALDRIG BARA 1FR. Ett spår på 1fr blir
        aldrig smalare än sitt innehålls minsta bredd, och en tabell
        med sex kolumner som inte får radbrytas har en minsta bredd
        på flera skärmar. Då växer spåret, panelen växer med det, och
        HELA SIDAN får en vågrät rullning - rubriken, brödtexten och
        menyn åker ut ur bild när man drar sig fram till tabellens
        sista kolumn. Nollan säger att spåret får bli smalare än sitt
        innehåll, och då tar tabellens egen rullning vid i stället,
        se .table-frame. Det är samma rad och samma skäl som i
        tvåspaltsläget ovan. */
    .admin {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-4);
    }

    /*  Samma spärr ett steg in.

        Spåret är kapat ovan, men innehållet i spåret är fortfarande
        ett rutnätsbarn - och ett sådant vägrar som standard bli
        smalare än sitt innehåll, alltså kan det svämma ut ur det
        kapade spåret på egen hand. */
    .admin__content {
        min-width: 0;
    }

    /*  Menyn blir en rad som RULLAR I SIDLED, inte en rad som bryts.

        En bruten rad ser ut som två olika saker: det sista valet
        hamnar ensamt under de andra och läses som en rubrik till det
        som kommer sedan. En rad som rullar håller ihop, och ett val
        som skjuter ut halvvägs vid kanten säger av sig själv att det
        finns mer att dra fram.

        DE NEGATIVA MARGINALERNA ÄR INTE ETT MISSTAG. De låter
        rullningen gå ända ut till skärmkanten medan valen ändå
        börjar i linje med innehållet ovanför - annars tar raden slut
        en centimeter från kanten och det sista valet ser ut att vara
        det sista som finns. Måttet är .site-main:s egen padding på
        den här bredden; ändras den ska den ändras här också.

        overflow-y: hidden hindrar att en lodrät rullning uppstår som
        bieffekt av den vågräta. */
    .admin__nav {
        position: static;

        flex-direction: row;
        flex-wrap: nowrap;
        align-items: center;
        gap: var(--space-2);

        margin: 0 calc(var(--space-4) * -1);
        padding: 0 var(--space-4);

        overflow-x: auto;
        overflow-y: hidden;
    }

    /*  Valen behåller sin bredd.

        Utan raden delar flexboxen ut den bredd som finns i stället
        för att låta raden bli bredare än skärmen - och då finns det
        ingenting att rulla, bara fyra hoptryckta val. */
    .admin__nav > * {
        flex: 0 0 auto;
        white-space: nowrap;
    }

    /*  Rubriken blir delens FÖRSTA val i raden i stället för en
        etikett ovanför den.

        Versalerna och den lilla texten hör hemma ovanför en lodrät
        lista, där de säger "det här är vad listan handlar om". Står
        de kvar i en rad BLAND valen läses de i stället som en rubrik
        till dem, alltså som något annat än en länk - och rubriken är
        en länk, till delens översikt. Se admin-head.php. */
    .admin__title {
        margin-bottom: 0;
        border-radius: var(--radius-md);

        font-size: var(--text-sm);
        font-weight: 500;
        letter-spacing: normal;
        text-transform: none;
    }

    /*  Är man på översikten markeras den som vilket val som helst.
        I spalten räcker en mörkare text, därför att rubriken står
        ensam ovanför listan. I raden står den bland valen och ska
        markeras på samma sätt som de. */
    .admin__title.is-current {
        background: var(--color-surface-strong);
    }

    /*  ETT FILTERFÄLT PER RAD.

        Att filtren står bredvid varandra bygger på att man ser dem
        alla samtidigt och ändrar ett i taget - se rutan vid
        .filter-bar. På en telefon blir det i stället två halva
        fält, och rullgardinen med händelsenamnen ryms inte i något
        av dem. flex-basis: 100% gör att en rad aldrig kan innehålla
        mer än ett fält.

        min-width: 0 är det som får den ordningen att hålla även när
        innehållet är brett. Utan raden vägrar fältet bli smalare än
        sin bredaste rullgardinsrad, och då sticker sidan ut utanför
        skärmen igen - av en annan orsak än den ovan, men med samma
        resultat. */
    .filter-bar .field {
        flex-basis: 100%;
        min-width: 0;
    }

    /*  Två spalter blir en. En etikett på 8 rem och ett värde
        bredvid får inte plats på en telefon. */
    .data-list {
        grid-template-columns: 1fr;
        gap: var(--space-1) 0;
    }

    .data-list dd {
        margin-bottom: var(--space-3);
    }

    .hero__heading {
        font-size: var(--text-2xl);
    }
}
