/* General layout rules that belong to no single component. */

/* Running text: 65 characters wide at most, no orphan on the last line. Headings balance their lines. */
p,
li,
blockquote {
    text-wrap: pretty;
}

p,
blockquote {
    max-width: 65ch;
}

/* A centered block of text (empty states) keeps its measure centered too */
:is(.text-center, .empty) p {
    margin-inline: auto;
}

h1,
h2,
h3,
.page-title,
.card-title,
.cb-card__title {
    text-wrap: balance;
}

/* A legal page: one reading column of about 70 characters, centered in the public frame */
.legal {
    max-width: 70ch;
    margin-inline: auto;

    :is(p, li, blockquote) {
        max-width: none;
    }
}

/* A flag of the language switcher (20 x 15 in the markup): a hairline so a white band does not melt into the surface */
.cb-flag {
    flex: none;
    box-shadow: 0 0 0 1px var(--line);
}

/* A link styled as a button, a card, a tab, a list or menu item never underlines: feedback comes from border, fill or shadow */
a:is(.btn, .card, .cb-card, .cb-object, .list-group-item, .dropdown-item, .nav-link) {
    &,
    &:hover,
    &:focus,
    &:active {
        text-decoration: none;
    }
}

/* A file input hidden behind its label styled as a button (the profile photo): the label carries the focus ring */
.visually-hidden:focus-visible + label.btn {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

/* 150ms on color changes of links and product components; users who ask for reduced motion get none */
@media (prefers-reduced-motion: no-preference) {
    :where(a, .cb-card, .cb-object, .cb-version) {
        transition:
            color 150ms,
            background-color 150ms,
            border-color 150ms,
            box-shadow 150ms;
    }

    /*
     * A menu opens in 150ms: it fades in and slides 4px from its button. The translate property leaves alone the transform
     * Popper positions a menu with. Closing stays instant.
     */
    .dropdown-menu.show {
        animation: cb-menu-in 150ms ease-out;
    }

    .dropup .dropdown-menu.show {
        --cb-menu-from: 4px;
    }

    @keyframes cb-menu-in {
        from {
            opacity: 0;
            translate: 0 var(--cb-menu-from, -4px);
        }
    }
}

/*
 * The environment banner (templates/_environment_banner.html.twig): pinned to the top of the window on every page of every
 * environment but production, and of every environment during a "signed in as" session. One line of 1.75rem per piece of
 * information, ellipsized rather than wrapped so that the height is known. The banner is a sibling of the page, not an
 * ancestor of the sidebar: a variable written on it never reaches the sidebar, so html holds the line height and the number
 * of lines (counted from the markup), and the scroll of the window, body and the sidebar read them from there.
 *
 * It is fixed, not sticky: Tabler gives body height: 100% and the page overflows it, and a sticky box stays inside its parent,
 * so it would let go after one window height of scrolling. Body makes room for it with its padding (border-box: its height
 * stays 100%, so .page keeps filling the window with no scroll of its own), and Tabler's sidebar, fixed to the window and
 * starting at its top edge, is pushed down by the same height.
 */
html:has(> body > .cb-env-banner) {
    --cb-env-banner-line: 1.75rem;
    --cb-env-banner-lines: 1;
    /* The lines and the 1px bottom edge of the banner */
    --cb-env-banner-height: calc(var(--cb-env-banner-lines) * var(--cb-env-banner-line) + 1px);

    /* The window scrolls on html, and only html's scroll-padding reaches it: a skip link, an anchor or a focused field stops under the banner */
    scroll-padding-block-start: var(--cb-env-banner-height);

    /* Two lines at most, the environment and "signed in as": a third line needs a third rule */
    &:has(> body > .cb-env-banner > .cb-env-banner__line:nth-child(2)) {
        --cb-env-banner-lines: 2;
    }
}

body:has(> .cb-env-banner) {
    padding-block-start: var(--cb-env-banner-height);

    /* The banner does not print: neither does its room */
    @media print {
        padding-block-start: 0;
    }

    /* Below the breakpoint the sidebar is a bar in the flow, under the banner already */
    @media (min-width: 992px) {
        .navbar-vertical.navbar-expand-lg {
            top: var(--cb-env-banner-height);
        }
    }
}

/* z-index: above Tabler's fixed sidebar (1030), under its offcanvas backdrop (1040), modals (1055) and toasts (1090) */
.cb-env-banner {
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    z-index: 1031;
    border-block-end: 1px solid var(--warning);
    background: var(--warning-soft);
    color: var(--ink);
}

/* display and column-gap repeat .cb-meta's for the "signed in as" line, which has no .cb-meta */
.cb-env-banner__line {
    display: flex;
    flex-wrap: nowrap;
    column-gap: var(--space-2);
    align-items: center;
    justify-content: center;
    height: var(--cb-env-banner-line);
    padding-inline: var(--space-4);
    font: 400 13px/20px var(--font-sans);
}

/* The stage name stays whole on a narrow screen: only the host ends in an ellipsis (.cb-meta) */
.cb-env-banner__line > :first-child {
    flex: none;
}

/* The "signed in as" line turns it around: the name ends in an ellipsis, and the button stays whole on a narrow screen */
.cb-env-banner__line:has(> form) {
    > :first-child {
        flex: 0 1 auto;
    }

    > form {
        flex: none;
    }

    /* btn-sm is 32px high: 26px here, inside the 28px line */
    .btn {
        --tblr-btn-padding-y: var(--space-1);
    }
}

/*
 * The frame (templates/layout/app.html.twig).
 * The sidebar is Tabler's vertical navbar: entries and footer are Tabler's own.
 * What follows tunes its measures to the charte (36px entries) and styles what Tabler has no class for: the title of a
 * group and the floating menu of the account.
 */
.cb-sidebar {
    /* Entries 36px high: 20px of line, 8px above and below (Tabler's 12px make 44px). The footer keeps its own 8px. */
    .navbar-nav {
        --tblr-sidebar-nav-padding-y: var(--space-2);
    }

    /* The current entry takes the icon in its own color; Tabler does that for .nav-item.active, the layout marks the link */
    .nav-link.active {
        --tblr-nav-link-icon-color: currentColor;
        font-weight: 600;
    }

    /* A hover on an entry fills with surface-sunken, like the account */
    .nav-link:not(.active):hover,
    .nav-link:not(.active):focus-visible,
    .nav-link:not(.active)[aria-expanded='true'] {
        background: var(--surface-sunken);
        color: var(--ink);
    }

    /*
     * The account at the foot: avatar, name, then the selector icon at the end of the line. Below the breakpoint Tabler keeps
     * the avatar alone and drops the border; the name stays, and so does the rule above the account.
     */
    .navbar-footer {
        margin-block-start: var(--space-2);
        padding-block: var(--space-2);
        border-block-start: 1px solid var(--line);

        .nav-link-title {
            display: block;
        }

        /* Above the breakpoint Tabler spaces the avatar itself, with a more specific rule */
        .nav-link .avatar {
            margin-inline-end: var(--space-2);
        }

        .nav-link > .icon {
            flex: none;
            margin-inline-start: auto;
            color: var(--ink-muted);
        }
    }

    /* The workspace filter under the logo: the name of the choice, then the selector icon at the end of the line. Inset like the entries (Tabler's sidebar inset, 8px). */
    .cb-workspace-filter {
        margin-inline: var(--space-2);
        margin-block-end: var(--space-4);

        > .btn {
            font-weight: 600;
        }
    }

    /*
     * Tabler unfolds any menu of the collapse in place, without surface: the footer grew upward and the account jumped
     * from under the pointer. The menus of the sidebar float instead, the width of their button, dressed like any
     * dropdown: the account's above it, the workspace filter's under it.
     */
    :is(.navbar-footer .dropup, .cb-workspace-filter) .dropdown-menu {
        position: absolute;
        z-index: var(--tblr-dropdown-zindex);
        min-width: 0;
        padding: var(--tblr-dropdown-padding-y) var(--tblr-dropdown-padding-x);
        background: var(--tblr-dropdown-bg);
        box-shadow: var(--tblr-dropdown-box-shadow);
        color: var(--tblr-dropdown-color);

        /* Tabler indents the entries of a sidebar menu by an icon; the buttons would shrink to their text */
        .dropdown-item {
            width: 100%;
            padding-inline: var(--tblr-dropdown-item-padding-x);
            border-radius: 0;
            color: var(--tblr-dropdown-link-color);
        }
    }

    .navbar-footer .dropup .dropdown-menu {
        inset: auto 0 100%;
        margin: 0 0 var(--space-1);
    }

    /* As specific as Tabler's rule of the collapse, which sets the margin to 0 */
    .cb-workspace-filter.dropdown .dropdown-menu {
        inset: 100% 0 auto;
        margin: var(--space-1) 0 0;
    }
}

/* Group of entries: the second one carries a title, small capitals in ink-muted aligned with the text of the entries (8px of inset + 12px of padding) */
.cb-nav-group + .cb-nav-group {
    margin-block-start: var(--space-4);
}

.cb-nav-group__title {
    margin: 0 var(--space-2);
    padding: var(--space-1) var(--space-3);
    color: var(--ink-muted);
    font: 600 11px/16px var(--font-sans);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* The title keeps room to read: when the actions of a page do not fit beside it (a client with its picture, its pieces and two buttons, on a phone), they wrap under it */
.page-header .row > .col {
    min-width: 14rem;
}

/*
 * The portal of a person of a client: the title and the page in one calm column, not the width of the team's screens.
 * The header and the footer keep the full width; the way back above the title is the size of a link, not of a label.
 */
.cb-portal {
    :is(.page-header, .page-body) > .container-xl {
        max-width: 46rem;
    }

    .page-pretitle {
        font-size: 0.875rem;
    }
}

/* A page of one form (invite a person, the access of a person): the title and the card in one column of 600px, centred */
.cb-narrow {
    :is(.page-header, .page-body) > .container-xl {
        max-width: calc(37.5rem + var(--tblr-gutter-x, 1.5rem));
    }
}

/*
 * The user guide (app., templates/support/guide/ and the HTML of App\Guide\GuideRenderer).
 * The navigation and the table of contents stay in view while the page scrolls, under the environment banner when there is one.
 */
.cb-guide-aside {
    @media (min-width: 992px) {
        position: sticky;
        inset-block-start: calc(var(--cb-env-banner-height, 0px) + var(--space-5));
        max-block-size: calc(100vh - var(--cb-env-banner-height, 0px) - var(--space-6));
        overflow-y: auto;
    }
}

.cb-guide-nav {
    .nav .nav {
        padding-inline-start: var(--space-3);
    }

    .nav-link {
        padding: var(--space-1) var(--space-3);
        border-radius: var(--radius-md);
        color: var(--ink-muted);

        &:hover,
        &:focus-visible {
            background: var(--surface-sunken);
            color: var(--ink);
        }

        &.active {
            background: var(--brand-soft);
            color: var(--ink);
            font-weight: 600;
        }
    }

    /* A category names its pages: it reads in ink, its pages in muted ink */
    .nav-link.fw-semibold {
        color: var(--ink);
    }
}

.cb-guide-toc li {
    padding-block: var(--space-1);
    font-size: 0.875rem;
}

/* The text of a page. Headings start at h2 (the title is the h1 of the template) and leave room for the anchors of the table of contents. */
.guide-content {
    overflow-wrap: anywhere;

    :is(h2, h3, h4) {
        margin-block: var(--space-6) var(--space-3);
        scroll-margin-block-start: var(--space-5);
    }

    :is(img, video, iframe) {
        max-width: 100%;
    }

    img {
        height: auto;
        border: 1px solid var(--line);
        border-radius: var(--radius-md);
    }

    /* A phone capture is taller than wide: phone width, centred, not stretched to the column */
    img.guide-img-portrait {
        display: block;
        max-width: min(100%, 20rem);
        margin-inline: auto;
    }

    /* A wide table scrolls inside the column instead of the page */
    table {
        display: block;
        max-width: 100%;
        overflow-x: auto;
    }

    :is(th, td) {
        padding: var(--space-2) var(--space-3);
        border-block-end: 1px solid var(--line);
        text-align: start;
    }

    pre {
        overflow-x: auto;
    }
}

/* [!NOTE], [!TIP], [!WARNING] and [!IMPORTANT]: Tabler's alert carries the tone (its info, success, warning and danger colors are the tokens'); the text stays in ink, which reads on every tint */
.guide-callout {
    color: var(--ink);
}

.guide-callout-title {
    margin-block-end: var(--space-1);
    font-weight: 600;
}

.guide-callout-body > :last-child {
    margin-block-end: 0;
}

/* A plain quote: set apart by a neutral rule and muted ink, no tone */
.guide-quote {
    margin-inline: 0;
    padding-inline-start: var(--space-4);
    border-inline-start: 2px solid var(--line-strong);
    color: var(--ink-muted);
}
