/* =========================================================================================
   m90Confluence theme
   =========================================================================================

   Five given colours, used as surfaces:

     #FFFFFF  white     content
     #FDF4D2  cream     titles
     #B0CDE6  blue      navigation and secondary surfaces
     #A290B7  purple    primary actions and the current selection
     #946D6D  rose      destructive and cautionary things

   Two things were derived rather than invented:

   * Washes. The full colours are too strong across a whole sidebar or page background, so
     large areas use them diluted with white. The named colours stay for bands and accents,
     where they read as deliberate rather than as a tint.

   * Darker variants for anything carrying WHITE text. Measured against WCAG AA (4.5:1):
     white on #A290B7 is only 2.91:1 and on #946D6D 4.50:1 -- right on the boundary. Buttons
     therefore use #746783 (5.24:1) and #765757 (6.42:1). The original colours are unchanged
     wherever dark text sits on them, which is everywhere else.

   Ink is #26232B rather than pure black: a near-black carrying a trace of the purple, which
   sits better on the cream than #000 does. 15.5:1 on white.
   ========================================================================================= */

:root {
    /* the palette, as given */
    --c-white: #FFFFFF;
    --c-cream: #FDF4D2;
    --c-blue: #B0CDE6;
    --c-purple: #A290B7;
    --c-rose: #946D6D;

    /* darkened, for white text only -- see the note above */
    --c-purple-deep: #746783;
    --c-rose-deep: #765757;
    --c-blue-deep: #667685;

    /* washes for large areas */
    --c-cream-wash: #FFFDF5;
    --c-blue-wash: #EEF4FA;
    --c-purple-wash: #EBE7EF;
    --c-rose-wash: #E7DFDF;

    /* lines, a step stronger than the wash they sit against */
    --c-cream-line: #F2E8C4;
    --c-blue-line: #D4E4F1;
    --c-purple-line: #CCC2D7;
    --c-rose-line: #C4AFAF;

    --c-ink: #26232B;
    --c-ink-muted: #6B6577;
    --c-line: #E4DFD6;
}

body {
    background: var(--c-cream-wash);
    color: var(--c-ink);
}

/* --- navigation ------------------------------------------------------------------------ */

.navbar {
    background: var(--c-white) !important;
    border-bottom: 1px solid var(--c-blue-line) !important;

    /* A thin blue rule under the bar, rather than a drop shadow: it separates the chrome
       from the page without adding depth the rest of the design does not use. */
    box-shadow: inset 0 -3px 0 var(--c-blue-wash) !important;
}

.navbar-brand {
    color: var(--c-purple-deep) !important;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.navbar .nav-link {
    color: var(--c-ink) !important;
    border-radius: 4px;
    padding-inline: .6rem;
}

.navbar .nav-link:hover,
.navbar .nav-link:focus {
    background: var(--c-blue-wash);
    color: var(--c-purple-deep) !important;
}

/* --- page titles ----------------------------------------------------------------------- */
/* The cream band is what the palette calls "title", so page headings get it. Applied to the
   h1 only, so a page with several headings does not turn into stripes. */

main > h1,
main > .row h1,
main h1.page-title {
    background: var(--c-cream);
    border-left: 4px solid var(--c-purple);
    border-radius: 0 6px 6px 0;
    padding: .6rem .9rem;
    margin-bottom: 1rem;
}

/* --- surfaces --------------------------------------------------------------------------- */

.card {
    background: var(--c-white);
    border: 1px solid var(--c-line);
    border-radius: 8px;
}

.card-header {
    background: var(--c-cream-wash);
    border-bottom: 1px solid var(--c-cream-line);
}

.list-group-item {
    background: var(--c-white);
    border-color: var(--c-line);
}

.list-group-item-action:hover {
    background: var(--c-blue-wash);
}

.breadcrumb {
    background: transparent;
    padding: .4rem 0;
}

.breadcrumb a {
    color: var(--c-purple-deep);
}

/* --- the space sidebar ------------------------------------------------------------------ */

.space-sidebar {
    background: var(--c-blue-wash);
    border: 1px solid var(--c-blue-line);
}

.tree-link {
    color: var(--c-ink);
}

.tree-link:hover {
    background: var(--c-white);
    color: var(--c-purple-deep);
}

.tree-link.active {
    background: var(--c-purple-wash);
    color: var(--c-purple-deep);
    box-shadow: inset 2px 0 0 var(--c-purple);
}

.space-sidebar-toggle:hover {
    color: var(--c-purple-deep);
}

/* --- buttons ----------------------------------------------------------------------------- */

.btn-primary {
    background: var(--c-purple-deep);
    border-color: var(--c-purple-deep);
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
    background: #63576F;
    border-color: #63576F;
}

.btn-outline-primary {
    color: var(--c-purple-deep);
    border-color: var(--c-purple);
}

.btn-outline-primary:hover {
    background: var(--c-purple-deep);
    border-color: var(--c-purple-deep);
    color: var(--c-white);
}

.btn-outline-secondary {
    color: var(--c-ink);
    border-color: var(--c-blue-line);
}

.btn-outline-secondary:hover {
    background: var(--c-blue-wash);
    border-color: var(--c-blue);
    color: var(--c-ink);
}

/* Destructive actions take the rose, which is the only colour here that reads as a caution
   without shouting. Bootstrap's own red is left alone for genuine errors. */
.btn-danger {
    background: var(--c-rose-deep);
    border-color: var(--c-rose-deep);
}

.btn-danger:hover,
.btn-danger:focus {
    background: #5F4646;
    border-color: #5F4646;
}

.btn-outline-danger {
    color: var(--c-rose-deep);
    border-color: var(--c-rose);
}

.btn-outline-danger:hover {
    background: var(--c-rose-deep);
    border-color: var(--c-rose-deep);
    color: var(--c-white);
}

.btn-link {
    color: var(--c-purple-deep);
}

a {
    color: var(--c-purple-deep);
}

a:hover {
    color: #63576F;
}

/* --- badges -------------------------------------------------------------------------------- */
/* Tinted fills with dark text, rather than saturated fills with white. At badge size the
   text is small, and small light-on-dark text is the first thing to become unreadable. */

.badge.text-bg-primary {
    background: var(--c-purple) !important;
    color: var(--c-ink) !important;
}

.badge.text-bg-secondary {
    background: var(--c-blue) !important;
    color: var(--c-ink) !important;
}

.badge.text-bg-light {
    background: var(--c-cream) !important;
    color: var(--c-ink) !important;
    border-color: var(--c-cream-line) !important;
}

/* Success, warning and danger keep their meaning -- a "live version" badge has to read as
   affirmative, and no colour in this palette does that. They are muted to sit alongside it. */
.badge.text-bg-success {
    background: #CFE3D4 !important;
    color: #1F3D28 !important;
}

.badge.text-bg-warning {
    background: var(--c-cream) !important;
    color: #6B5518 !important;
}

.badge.text-bg-danger {
    background: var(--c-rose-deep) !important;
    color: var(--c-white) !important;
}

/* --- alerts ---------------------------------------------------------------------------------- */

.alert-info {
    background: var(--c-blue-wash);
    border-color: var(--c-blue-line);
    color: var(--c-ink);
}

.alert-secondary {
    background: var(--c-purple-wash);
    border-color: var(--c-purple-line);
    color: var(--c-ink);
}

.alert-warning {
    background: var(--c-cream);
    border-color: var(--c-cream-line);
    color: var(--c-ink);
}

.alert-success {
    background: #E4F0E7;
    border-color: #C3DCCA;
    color: #1F3D28;
}

.alert-danger {
    background: var(--c-rose-wash);
    border-color: var(--c-rose-line);
    color: #4A3636;
}

/* --- tables ------------------------------------------------------------------------------------ */

.table > thead {
    background: var(--c-blue-wash);
}

.table > thead th {
    border-bottom-color: var(--c-blue-line);
    font-weight: 600;
}

.table-hover > tbody > tr:hover > * {
    background: var(--c-cream-wash);
}

.table-active > * {
    background: var(--c-purple-wash) !important;
}

/* --- forms -------------------------------------------------------------------------------------- */

.form-control:focus,
.form-select:focus,
.form-check-input:focus {
    border-color: var(--c-purple);
    box-shadow: 0 0 0 .2rem var(--c-purple-wash);
}

.form-check-input:checked {
    background-color: var(--c-purple-deep);
    border-color: var(--c-purple-deep);
}

/* Overrides the white-then-blue focus ring inherited from the project template, which does
   not belong against these softer surfaces. */
.btn:focus,
.btn:active:focus,
.btn-link.nav-link:focus,
.form-control:focus,
.form-check-input:focus {
    box-shadow: 0 0 0 .2rem var(--c-purple-wash);
}

/* --- page content ---------------------------------------------------------------------------------- */

.page-content blockquote {
    border-left-color: var(--c-purple);
    background: var(--c-purple-wash);
    padding: .5rem .9rem;
    border-radius: 0 4px 4px 0;
    color: var(--c-ink);
}

.page-content pre,
.page-content .ql-syntax,
.page-content .ql-code-block-container {
    background: var(--c-blue-wash);
    border: 1px solid var(--c-blue-line);
}

.page-content th {
    background: var(--c-blue-wash);
}

.page-content th,
.page-content td {
    border-color: var(--c-blue-line);
}

.comment {
    border-left-color: var(--c-blue);
}

.comment-body {
    color: var(--c-ink);
}

/* --- the editor -------------------------------------------------------------------------------------- */

.ql-toolbar.ql-snow {
    background: var(--c-cream-wash);
    border-color: var(--c-line) !important;
    border-radius: 6px 6px 0 0;
}

.ql-container.ql-snow {
    border-color: var(--c-line) !important;
    border-radius: 0 0 6px 6px;
}

#editor {
    background: var(--c-white);
}

/* --- version comparison ---------------------------------------------------------------------------------- */
/* Insert and delete stay green and red. They carry meaning that no palette colour conveys,
   and a diff whose colours are merely decorative is worse than no colour at all. Softened
   to sit alongside the rest. */

.diff-inserted { background: #DFEEE4; }
.diff-deleted  { background: var(--c-rose-wash); }
.diff-modified { background: var(--c-cream); }
.diff-blank    { background: var(--c-blue-wash); }

/* --- footer ------------------------------------------------------------------------------------------------- */

.footer {
    border-top-color: var(--c-blue-line) !important;
    color: var(--c-ink-muted) !important;
}

/* --- the sign-in page ----------------------------------------------------------------------------------------- */

.login-card {
    border-color: var(--c-blue-line) !important;
    box-shadow: 0 1px 3px rgba(38, 35, 43, .08) !important;
}

.login-card h1 {
    color: var(--c-purple-deep);
}

/* =========================================================================================
   Macros
   ========================================================================================= */

.macro-toc {
    background: var(--c-blue-wash);
    border: 1px solid var(--c-blue-line);
    border-radius: 6px;
    padding: .75rem 1rem;
    margin: 1rem 0;
    max-width: 26rem;
}

.macro-toc-title {
    font-weight: 600;
    font-size: .85rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-muted);
    margin-bottom: .35rem;
}

.macro-toc ul { list-style: none; margin: 0; padding: 0; }
.macro-toc li { line-height: 1.5; }
.macro-toc a { text-decoration: none; }
.macro-toc a:hover { text-decoration: underline; }

.toc-level-1 { padding-left: 1rem; }
.toc-level-2 { padding-left: 2rem; }
.toc-level-3 { padding-left: 3rem; }

.macro-children {
    background: var(--c-cream-wash);
    border: 1px solid var(--c-cream-line);
    border-radius: 6px;
    padding: .75rem 1rem .75rem 2rem;
    margin: 1rem 0;
    max-width: 32rem;
}

.macro-empty {
    color: var(--c-ink-muted);
    font-style: italic;
    padding: .5rem .75rem;
}

.macro-panel {
    border-radius: 6px;
    padding: .75rem 1rem;
    margin: 1rem 0;
    border-left: 4px solid;
}

.macro-panel-label {
    font-weight: 600;
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-bottom: .25rem;
}

.macro-panel-body > :last-child { margin-bottom: 0; }

.macro-panel-info {
    background: var(--c-blue-wash);
    border-left-color: var(--c-blue);
}

.macro-panel-info .macro-panel-label { color: var(--c-blue-deep); }

.macro-panel-warning {
    background: var(--c-rose-wash);
    border-left-color: var(--c-rose);
}

.macro-panel-warning .macro-panel-label { color: var(--c-rose-deep); }

/* Status badges. The tone is derived from the word itself, so DONE reads as settled without
   the author having to choose a colour. */
.macro-status {
    display: inline-block;
    padding: .15rem .5rem;
    border-radius: 3px;
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    vertical-align: baseline;
}

.macro-status-draft   { background: var(--c-cream);      color: #6B5518; border: 1px solid var(--c-cream-line); }
.macro-status-review  { background: var(--c-purple-wash); color: var(--c-purple-deep); border: 1px solid var(--c-purple-line); }
.macro-status-done    { background: #DFEEE4;             color: #1F3D28; border: 1px solid #C3DCCA; }
.macro-status-blocked { background: var(--c-rose-deep);  color: #fff; }

.macro-expand {
    background: var(--c-white);
    border: 1px solid var(--c-line);
    border-radius: 6px;
    padding: .5rem .9rem;
    margin: 1rem 0;
}

.macro-expand > summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--c-purple-deep);
}

.macro-expand-body {
    padding-top: .5rem;
    margin-top: .5rem;
    border-top: 1px solid var(--c-line);
}

.macro-expand-body > :last-child { margin-bottom: 0; }

/* The editor's own macro buttons: text labels, since Quill's icon set has nothing for these. */
.macro-buttons .macro-insert {
    width: auto !important;
    padding: 0 .4rem !important;
    font-size: .72rem;
    font-weight: 600;
    color: var(--c-purple-deep);
    background: var(--c-purple-wash);
    border: 1px solid var(--c-purple-line) !important;
    border-radius: 3px;
    margin-right: .15rem;
}

.macro-buttons .macro-insert:hover {
    background: var(--c-purple);
    color: var(--c-ink);
}

/* A placeholder inside the editor, so the author can see that something is there. */
.ql-editor [data-macro] {
    background: var(--c-purple-wash);
    border: 1px dashed var(--c-purple);
    border-radius: 4px;
    padding: .4rem .6rem;
    margin: .5rem 0;
    position: relative;
}

.ql-editor [data-macro]::before {
    content: "macro: " attr(data-macro);
    display: block;
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--c-purple-deep);
    margin-bottom: .2rem;
}


/* =========================================================================================
   Print
   =========================================================================================
   The browser's own Print -> Save as PDF is the export route for PDF: headless Chrome will
   not run on shared IIS hosting, so a print stylesheet is what makes that produce something
   worth keeping rather than a screenshot of the application.
   ========================================================================================= */

@media print {
    /* Everything that is navigation or an action rather than content. */
    .navbar,
    .footer,
    .space-sidebar,
    .breadcrumb,
    .btn,
    .btn-group,
    form,
    .alert,
    .d-print-none,
    .comment-thread,
    .macro-buttons {
        display: none !important;
    }

    body {
        background: #fff !important;
        color: #000;
        font-size: 11pt;
    }

    /* The content column takes the full width once the sidebar is gone. */
    .col-lg-9,
    .col-12 {
        width: 100% !important;
        max-width: 100% !important;
        flex: 0 0 100% !important;
    }

    .container { max-width: none !important; width: 100% !important; padding: 0 !important; }

    main > h1,
    main h1.page-title {
        background: none !important;
        border-left: none !important;
        padding: 0 !important;
        font-size: 20pt;
    }

    /* Links are useless on paper unless the address is visible. Skipped for in-page anchors,
       which would otherwise litter a table of contents with "(#heading)". */
    .page-content a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: 9pt;
        color: #555;
    }

    /* Keep a heading with the text beneath it, and never break a panel across a page. */
    h1, h2, h3, h4 { break-after: avoid-page; page-break-after: avoid; }
    .macro-panel, .macro-toc, table, pre, blockquote { break-inside: avoid; page-break-inside: avoid; }

    .macro-expand > summary { font-weight: 700; }
    .macro-expand-body { display: block !important; }   /* print collapsed detail too */

    .page-content pre,
    .page-content blockquote,
    .macro-panel,
    .macro-toc {
        border: 1px solid #ccc !important;
        background: #fafafa !important;
    }

    a { color: #000; text-decoration: underline; }
}

/* =========================================================================================
   Welcome banner and the page reading surface
   ========================================================================================= */

/* The reading area, set apart from the metadata above and the comments below. White on the
   cream page background, so the eye lands on the content rather than hunting for where it
   starts. */
.page-body {
    display: block;
    background: var(--c-white);
    border: 1px solid var(--c-line);
    border-radius: 8px;
    padding: 1.5rem 1.75rem;
    margin-bottom: 1.25rem;
}

@media (max-width: 575.98px) {
    .page-body { padding: 1rem; }
}

.page-body > .page-content > :last-child { margin-bottom: 0; }

/* Checklists, rendered with box glyphs. Not interactive: a checkbox whose state nobody
   stores is a promise the application cannot keep. */
.page-content ul.m90-checklist {
    list-style: none;
    padding-left: 1.2rem;
}

.page-content ul.m90-checklist li::before {
    content: "\2610\00a0\00a0";
    color: var(--c-purple-deep);
}

.page-content ul.m90-checklist li.done::before {
    content: "\2611\00a0\00a0";
}

.page-content ul.m90-checklist li.done {
    color: var(--c-ink-muted);
    text-decoration: line-through;
}

@media print {
    .page-body { border: none !important; padding: 0 !important; }
}

/* On a phone the sidebar starts collapsed, so its header carries the whole space identity:
   name, key and the actions menu all stay reachable without expanding the tree. */
@media (max-width: 991.98px) {
    .space-sidebar {
        position: static;
        max-height: none;
        padding: .6rem .75rem;
    }

    .space-sidebar-body[hidden] {
        display: none !important;
    }
}


/* =========================================================================================
   Space sidebar: let its menu escape the box
   =========================================================================================
   site.css gives the sidebar `max-height` and `overflow-y: auto` on wide screens, which makes
   it a scroll container -- and an absolutely positioned dropdown inside a scroll container is
   clipped by it. The menu was being cut off, and reaching the last item meant scrolling the
   sidebar rather than the menu.

   The fix is to move the scrolling one level in. The sidebar itself no longer clips anything;
   the page TREE scrolls instead, which is the part that actually grows without limit. The
   header and its menu sit outside that, so the menu opens over the page content at full
   height. This also keeps working on a phone, where the tree is collapsed and the header --
   menu included -- is all that remains.
   ========================================================================================= */

.space-sidebar {
    overflow: visible;
    max-height: none;
}

@media (min-width: 992px) {
    .space-sidebar {
        position: sticky;
        top: 1rem;
        max-height: none;
        overflow: visible;
    }

    /* The tree is the part that can grow to hundreds of entries, so it takes the scrollbar. */
    .space-sidebar-body {
        max-height: calc(100vh - 10rem);
        overflow-y: auto;
        overflow-x: hidden;
    }
}

/* Above the sticky sidebar and the page content it now opens over. */
.space-sidebar .dropdown-menu {
    z-index: 1035;

    /* A floor under the menu on a short window: it scrolls itself rather than being cut off
       by the viewport, which is ordinary dropdown behaviour and not the bug being fixed. */
    max-height: min(75vh, 28rem);
    overflow-y: auto;
}

@media (max-width: 991.98px) {
    /* Collapsed by default here, so the header carries everything. Nothing clips the menu. */
    .space-sidebar {
        position: static;
        max-height: none;
        overflow: visible;
        padding: .6rem .75rem;
    }

    .space-sidebar-body {
        max-height: none;
        overflow: visible;
    }

    /* Full width on a phone, so the longest label is not squeezed. */
    .space-sidebar .dropdown-menu {
        min-width: 14rem;
    }
}

/* =========================================================================================
   Image thumbnails
   =========================================================================================
   Images get a visual preview; every other attachment stays a filename in a list, because a
   thumbnail of a spreadsheet tells the reader nothing.

   The preview is the full image scaled by the browser rather than a separately generated
   thumbnail. That keeps the feature free of an image-processing dependency, and `loading`
   is set to lazy so pictures below the fold are not fetched until they are scrolled to. The
   trade-off is bandwidth on a page carrying many large photographs -- see the note in the
   handover if that becomes the common case.
   ========================================================================================= */

.thumb-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .75rem;
    max-width: 40rem;
}

.thumb {
    margin: 0;
    position: relative;
}

.thumb > a {
    display: block;
    border: 1px solid var(--c-blue-line);
    border-radius: 6px;
    overflow: hidden;
    background: var(--c-blue-wash);

    /* A fixed shape so a row of mixed portrait and landscape photographs still lines up. */
    aspect-ratio: 4 / 3;
    cursor: zoom-in;
}

.thumb > a:hover {
    border-color: var(--c-purple);
}

.thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.thumb figcaption {
    font-size: .75rem;
    color: var(--c-ink-muted);
    margin-top: .25rem;
    line-height: 1.3;
}

.thumb-name {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.thumb-size {
    display: block;
    opacity: .8;
}

/* The remove control sits over the corner of the image, and stays out of the way until the
   pointer is on the thumbnail. */
.thumb-remove {
    position: absolute;
    top: .25rem;
    right: .25rem;
    opacity: 0;
    transition: opacity .12s ease-in-out;
}

.thumb:hover .thumb-remove,
.thumb-remove:focus-within {
    opacity: 1;
}

.thumb-remove button {
    background: rgba(38, 35, 43, .75);
    color: #fff;
    border: 0;
    border-radius: 4px;
    line-height: 1;
    padding: .1rem .35rem;
}

.thumb-remove button:hover {
    background: var(--c-rose-deep);
    color: #fff;
}

/* The full-size view, opened by clicking a thumbnail. */
.lightbox {
    position: fixed;
    inset: 0;
    background: rgba(38, 35, 43, .92);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    z-index: 2000;
    padding: 2rem;
    cursor: zoom-out;
}

.lightbox img {
    max-width: 100%;
    max-height: calc(100% - 3rem);
    object-fit: contain;
    border-radius: 4px;
}

.lightbox figcaption {
    color: #fff;
    font-size: .85rem;
    margin-top: .75rem;
    text-align: center;
}

.lightbox .lightbox-hint {
    color: rgba(255, 255, 255, .6);
    font-size: .75rem;
    margin-top: .25rem;
}

@media print {
    .thumb-remove { display: none !important; }
    .thumb-grid { grid-template-columns: repeat(3, 1fr); }
}

/* =========================================================================================
   Square edges
   =========================================================================================
   Everything loses its corner radius: cards, buttons, inputs, badges, alerts, panels,
   thumbnails, the sidebar, the page body, macro blocks and the editor.

   Done as one sweeping rule rather than by hunting down every declaration. There are twenty
   radii in our own stylesheets and a great many more inherited from Bootstrap, and the
   sweeping version cannot miss one -- nor can a component added next month quietly arrive
   with rounded corners.

   The `rounded` and `rounded-pill` utility classes are covered by the same rule, so markup
   using them needs no change.
   ========================================================================================= */

*,
*::before,
*::after {
    border-radius: 0 !important;
}

/* One exception, and it is not decorative. A radio button is round because that is what
   distinguishes it from a checkbox -- squaring it would make "pick exactly one" look like
   "tick any that apply". The shape is carrying meaning, so it stays. */
input[type="radio"],
.form-check-input[type="radio"] {
    border-radius: 50% !important;
}


/* =========================================================================================
   The page tree, drawn like a desktop file explorer
   =========================================================================================
   Guide lines, a twisty on anything with children, and folder/document icons.

   The indent and the lines are pure CSS on a plain nested <ul>. Nothing is positioned by
   depth from the server, so a tree ten levels deep needs no extra rules -- and the markup
   stays a real list, which is what a screen reader wants.

   The vertical line is a left border on the nested list; the little elbow into each row is a
   pseudo-element. The last child covers the tail of the line with a matching background so
   the elbow terminates rather than running past the final item, which is what a real
   explorer does.
   ========================================================================================= */

.tree,
.tree ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.tree ul {
    /* the guide line for this level */
    margin-left: .6rem;
    border-left: 1px solid var(--c-line);
}

.tree-node {
    position: relative;
}

/* the elbow joining the guide line to the row */
.tree ul > .tree-node::before {
    content: "";
    position: absolute;
    left: 0;
    top: .9rem;
    width: .55rem;
    border-top: 1px solid var(--c-line);
}

/* stop the guide line at the last item, so it does not overshoot */
.tree ul > .tree-node:last-child::after {
    content: "";
    position: absolute;
    left: -1px;
    top: .9rem;
    bottom: 0;
    border-left: 1px solid var(--c-surface, #fff);
}

.tree-row {
    display: flex;
    align-items: center;
    gap: .15rem;
    padding: .1rem .25rem .1rem .55rem;
    min-height: 1.6rem;
}

.tree-row:hover {
    background-color: var(--c-blue-wash);
}

.tree-row.active {
    background-color: var(--c-blue);
}

.tree-row.active .tree-link {
    font-weight: 600;
}

/* The twisty. A CSS triangle rather than a glyph, so it cannot be affected by the reader's
   font and lines up identically at every level. */
.tree-twisty {
    flex: 0 0 auto;
    width: 1rem;
    height: 1rem;
    padding: 0;
    border: 0;
    background: none;
    position: relative;
    cursor: pointer;
}

.tree-twisty::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-left: .3rem solid var(--c-ink-muted);
    border-top: .25rem solid transparent;
    border-bottom: .25rem solid transparent;
}

.tree-node.open > .tree-row > .tree-twisty::before {
    transform: translate(-50%, -50%) rotate(90deg);
}

.tree-twisty-empty {
    cursor: default;
}

.tree-twisty-empty::before {
    content: none;
}

/* Folder and document marks. Drawn in CSS so there is no icon font or sprite to ship. */
.tree-icon {
    flex: 0 0 auto;
    width: .95rem;
    height: .8rem;
    margin-right: .2rem;
    position: relative;
}

.tree-icon.is-folder::before {
    content: "";
    position: absolute;
    inset: .05rem 0 0 0;
    background: var(--c-cream);
    border: 1px solid var(--c-cream-line);
    border-top-width: .18rem;
    border-top-color: var(--c-rose);
}

.tree-icon.is-doc::before {
    content: "";
    position: absolute;
    inset: 0 .18rem 0 .18rem;
    background: var(--c-white);
    border: 1px solid var(--c-line);
}

.tree-link {
    display: block;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0 .15rem;
    color: var(--c-ink);
    text-decoration: none;
    font-size: .875rem;
    line-height: 1.3;

    /* A long title truncates rather than wrapping to three lines and destroying the
       alignment of the guide lines. The full text stays available on hover and to a
       screen reader. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tree-link:hover {
    text-decoration: underline;
}

/* Collapsed: hide the children. Driven by the class, so it works before site.js loads. */
.tree-node.has-children:not(.open) > ul {
    display: none;
}


/* =========================================================================================
   The space panel header: two rows on a desktop, one on a phone
   =========================================================================================
   On a wide screen the space key and the actions menu take their own line and the space name
   sits underneath with the tree, so a long name gets the full width instead of being crushed
   against the menu button. On a phone that would cost a line of vertical space for nothing,
   so the two stay side by side.
   ========================================================================================= */

.space-sidebar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;

    /* No row gap. The space name is the root of the tree, not a heading above it, so any
       space between the two reads as a break in the structure. Rows that do need breathing
       room ask for it themselves -- see .space-sidebar-foot. */
    gap: 0;
}

/* Row one: the space name, on its own, taking the full width. */
.space-sidebar-toggle { flex: 1 1 100%; min-width: 0; }

/* Row two: the tree. */
.space-sidebar-body { flex: 1 1 100%; }

/* Row three: create and the actions menu, side by side at the foot. */
.space-sidebar-foot {
    flex: 1 1 100%;
    display: flex;
    align-items: center;
    gap: .4rem;
    margin-top: .75rem;
}

.space-sidebar-create { flex: 1 1 auto; }
.space-sidebar-foot .dropdown { flex: 0 0 auto; }


/* =========================================================================================
   Dark mode
   =========================================================================================
   Switched on by data-mode="dark" on <html>, set inline in the head before the first paint.
   The reader chooses it from the account menu and the choice is remembered per device.

   Almost all of this is one block of token redefinitions, because the light theme was built
   on variables. What follows the tokens is the part that cannot be: Bootstrap's own
   components carry hardcoded light colours of their own, so cards, menus, inputs, tables and
   the light utility classes each need restating.

   Note what does NOT change: the brand bar keeps #1a65a6. It is the one fixed point of the
   identity, it already carries white text, and a dark surface reads perfectly well beneath
   it. Inverting it would make the application look like a different product at night.
   ========================================================================================= */

:root[data-mode="dark"] {
    /* surfaces, from the page ground upward */
    --c-cream-wash: #14171c;   /* body */
    --c-white: #1c2027;        /* raised surfaces: cards, the editor, page body */
    --c-surface: #1c2027;
    --c-cream: #262b34;

    /* the accents, pulled down to sit under light text */
    --c-blue: #2d4c66;
    --c-purple: #493e56;
    --c-rose: #5a4444;

    --c-blue-wash: #1a2530;
    --c-purple-wash: #221d29;
    --c-rose-wash: #291f1f;

    --c-cream-line: #333a45;
    --c-blue-line: #2f4356;
    --c-purple-line: #3d3448;
    --c-rose-line: #4a3939;

    /* text and rules */
    --c-ink: #e4e1e8;
    --c-ink-muted: #9d97a8;
    --c-line: #333945;
}

/* --- Bootstrap's own components, which do not read our tokens ------------------------- */

:root[data-mode="dark"] .card,
:root[data-mode="dark"] .list-group-item,
:root[data-mode="dark"] .modal-content,
:root[data-mode="dark"] .accordion-item {
    background-color: var(--c-white);
    color: var(--c-ink);
    border-color: var(--c-line);
}

:root[data-mode="dark"] .dropdown-menu {
    background-color: var(--c-white);
    border-color: var(--c-line);
}

:root[data-mode="dark"] .dropdown-item {
    color: var(--c-ink);
}

:root[data-mode="dark"] .dropdown-item:hover,
:root[data-mode="dark"] .dropdown-item:focus {
    background-color: var(--c-blue-wash);
    color: var(--c-ink);
}

:root[data-mode="dark"] .dropdown-divider {
    border-top-color: var(--c-line);
}

/* Inputs. The border is deliberately a step lighter than the surrounding rule: a field the
   reader is expected to type into should be findable without hunting for its edge. */
:root[data-mode="dark"] .form-control,
:root[data-mode="dark"] .form-select {
    background-color: #11141a;
    border-color: #3f4654;
    color: var(--c-ink);
}

:root[data-mode="dark"] .form-control:focus,
:root[data-mode="dark"] .form-select:focus {
    background-color: #11141a;
    color: var(--c-ink);
    border-color: var(--c-brand);
    box-shadow: 0 0 0 .2rem rgba(26, 101, 166, .35);
}

:root[data-mode="dark"] .form-control::placeholder {
    color: #7d8595;
}

:root[data-mode="dark"] .input-group-text {
    background-color: var(--c-cream);
    border-color: #3f4654;
    color: var(--c-ink);
}

:root[data-mode="dark"] .table {
    --bs-table-color: var(--c-ink);
    --bs-table-bg: transparent;
    --bs-table-border-color: var(--c-line);
    --bs-table-striped-color: var(--c-ink);
    --bs-table-striped-bg: rgba(255, 255, 255, .035);
    --bs-table-hover-color: var(--c-ink);
    --bs-table-hover-bg: rgba(255, 255, 255, .055);
}

/* The light utility classes are used throughout the markup for panels and badges. */
:root[data-mode="dark"] .bg-white,
:root[data-mode="dark"] .bg-light {
    background-color: var(--c-white) !important;
}

:root[data-mode="dark"] .text-dark {
    color: var(--c-ink) !important;
}

:root[data-mode="dark"] .text-muted {
    color: var(--c-ink-muted) !important;
}

:root[data-mode="dark"] .border,
:root[data-mode="dark"] .border-top,
:root[data-mode="dark"] .border-bottom,
:root[data-mode="dark"] .border-start,
:root[data-mode="dark"] .border-end {
    border-color: var(--c-line) !important;
}

:root[data-mode="dark"] .badge.text-bg-light {
    background-color: var(--c-cream) !important;
    color: var(--c-ink) !important;
}

/* Alerts: Bootstrap's pastel fills go muddy on a dark ground, so they are restated as a
   tinted wash with a coloured left edge carrying the meaning. */
:root[data-mode="dark"] .alert {
    background-color: var(--c-cream);
    border-color: var(--c-line);
    color: var(--c-ink);
}

:root[data-mode="dark"] .alert-info { border-left: .25rem solid #3d7fb5; }
:root[data-mode="dark"] .alert-warning { border-left: .25rem solid #b58a3d; }
:root[data-mode="dark"] .alert-danger { border-left: .25rem solid #b5563d; }
:root[data-mode="dark"] .alert-success { border-left: .25rem solid #4f9d5e; }

:root[data-mode="dark"] .alert a {
    color: #8dc2ea;
}

/* Code and preformatted text. */
:root[data-mode="dark"] code,
:root[data-mode="dark"] pre,
:root[data-mode="dark"] .font-monospace {
    color: #e0d7b8;
}

:root[data-mode="dark"] pre {
    background-color: #11141a;
    border-color: var(--c-line);
}

/* Links inside prose. The light theme's link colour is too dark to read here. */
:root[data-mode="dark"] a {
    color: #8dc2ea;
}

:root[data-mode="dark"] .btn-link {
    color: #8dc2ea;
}

/* Outline buttons: the default border and label are near-black. */
:root[data-mode="dark"] .btn-outline-secondary {
    color: var(--c-ink);
    border-color: #4a5261;
}

:root[data-mode="dark"] .btn-outline-secondary:hover {
    background-color: #2b313b;
    color: var(--c-ink);
    border-color: #5a6272;
}

/* The rich text editor is an iframe with its own document, so its chrome is styled here and
   its content area is handed a matching background by the editor configuration. */
:root[data-mode="dark"] .tox .tox-toolbar__primary,
:root[data-mode="dark"] .tox .tox-editor-header,
:root[data-mode="dark"] .tox .tox-menubar {
    background-color: var(--c-cream) !important;
}

:root[data-mode="dark"] .tox-tinymce {
    border-color: var(--c-line) !important;
}


/* =========================================================================================
   The page panel: title, body and byline as one sheet
   =========================================================================================
   The title used to sit on a cream bar with the white reading card beneath it, which read as
   two unrelated blocks. Here they are one bordered sheet -- header, body, footer -- so the
   page looks like a single document rather than a stack.

   Everything is a surface token, so dark mode turns the whole panel together and no part of
   it is left stranded on the wrong background.
   ========================================================================================= */

.page-panel {
    display: block;
    background: var(--c-white);
    border: 1px solid var(--c-line);
    margin-bottom: 1.25rem;
}

.page-panel-head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: .75rem;

    padding: 1rem 1.75rem .75rem;

    /* The only division inside the sheet, and a faint one: enough to separate the header
       from the prose, not enough to look like a second box. */
    border-bottom: 1px solid var(--c-line);
}

.page-panel-title {
    margin: 0;
    font-size: 1.6rem;
    line-height: 1.25;
    font-weight: 600;
    color: var(--c-ink);

    /* Beat the generic heading rule, which would otherwise put the cream bar back. */
    background: none;
    border-left: 0;
    padding: 0;
}

.page-panel-body {
    padding: 1.5rem 1.75rem;
}

.page-panel-body > .page-content > :last-child {
    margin-bottom: 0;
}

.page-panel-meta {
    padding: .7rem 1.75rem .8rem;
    border-top: 1px solid var(--c-line);
    font-size: .8125rem;
    color: var(--c-ink-muted);
}

@media (max-width: 575.98px) {
    .page-panel-head { padding: .85rem 1rem .7rem; }
    .page-panel-body { padding: 1rem; }
    .page-panel-meta { padding: .6rem 1rem; }
    .page-panel-title { font-size: 1.35rem; }
}


/* =========================================================================================
   Page background tints
   =========================================================================================
   Seven choices, all of them barely there. The point is a change of temperature behind the
   reading panel, not a colour scheme -- anything stronger competes with the content, and the
   white panel has to stay clearly the brightest thing on the page.

   Guarded against dark mode: :not([data-mode="dark"]) means a reader who picked pink and then
   switched to dark gets a proper dark ground, with the pink waiting for them if they switch
   back.
   ========================================================================================= */

:root:not([data-mode="dark"])[data-tint="white"]  { --c-cream-wash: #ffffff; }
:root:not([data-mode="dark"])[data-tint="grey"]   { --c-cream-wash: #f4f5f6; }
:root:not([data-mode="dark"])[data-tint="green"]  { --c-cream-wash: #f2f7f2; }
:root:not([data-mode="dark"])[data-tint="blue"]   { --c-cream-wash: #f1f5fa; }
:root:not([data-mode="dark"])[data-tint="pink"]   { --c-cream-wash: #faf2f4; }
:root:not([data-mode="dark"])[data-tint="purple"] { --c-cream-wash: #f5f2f8; }

/* On white, the panel would vanish into the page, so its edge earns a little more weight. */
:root:not([data-mode="dark"])[data-tint="white"] .page-panel,
:root:not([data-mode="dark"])[data-tint="white"] .page-body,
:root:not([data-mode="dark"])[data-tint="white"] .card {
    border-color: #dcdcdc;
}

/* --- the swatch picker in the account menu --------------------------------------------- */

.tint-picker {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    margin: 0;
}

.tint-swatch {
    width: 1.35rem;
    height: 1.35rem;
    padding: 0;
    border: 1px solid var(--c-line);
    cursor: pointer;
}

.tint-swatch:hover {
    border-color: var(--c-ink-muted);
}

/* The chosen one is marked with a ring rather than a tick: at this size a glyph would be
   illegible, and the ring survives on every tint including white. */
.tint-swatch.chosen {
    outline: 2px solid var(--c-brand);
    outline-offset: 1px;
    border-color: var(--c-brand);
}

.tint-default { background: #fdf9ec; }
.tint-white   { background: #ffffff; }
.tint-grey    { background: #f4f5f6; }
.tint-green   { background: #f2f7f2; }
.tint-blue    { background: #f1f5fa; }
.tint-pink    { background: #faf2f4; }
.tint-purple  { background: #f5f2f8; }


/* =========================================================================================
   The AI summary panel
   =========================================================================================
   Collapsed by default. It is written for machines rather than people, so it should be
   findable without taking up room on a page nobody is reading it on.
   ========================================================================================= */

/* A bordered, collapsible box. Used by the page icon picker and the AI summary, so the two
   read as siblings rather than as one long run of controls under the page. */
.page-box {
    border: 1px solid var(--c-line);
    background: var(--c-white);
}

.page-box-head {
    padding: .6rem .9rem;
    cursor: pointer;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    color: var(--c-ink);
}

.page-box-head:hover {
    background: var(--c-blue-wash);
}

.page-box[open] .page-box-head {
    border-bottom: 1px solid var(--c-line);
}

.page-box-body {
    padding: .9rem;
}

/* Thirteen groups of icons is taller than a screen, so the box scrolls rather than pushing
   everything below it a long way down the page. */
#iconPicker .page-box-body {
    max-height: 22rem;
    overflow-y: auto;
}

/* Read-only, and it should look it: no white field inviting a cursor. */
.page-box-body textarea[readonly] {
    background: var(--c-cream-wash);
    resize: vertical;
}


/* =========================================================================================
   Page icons
   ========================================================================================= */

.page-icon {
    /* Slightly below the cap height of the text beside it, so it sits on the line rather
       than towering over a title. */
    font-size: .9em;
    line-height: 1;
    margin-right: .3rem;
}

.icon-group {
    margin-bottom: .75rem;
}

.icon-grid {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-top: .2rem;
}

.icon-choice {
    width: 2.1rem;
    height: 2.1rem;
    font-size: 1.15rem;
    line-height: 1;
    padding: 0;
    border: 1px solid var(--c-line);
    background: var(--c-white);
    cursor: pointer;
}

.icon-choice:hover {
    background: var(--c-blue-wash);
    border-color: var(--c-ink-muted);
}

/* The one in use, marked with a ring rather than a tick -- a tick on top of an emoji is
   unreadable at this size. */
.icon-choice.chosen {
    outline: 2px solid var(--c-brand);
    outline-offset: 1px;
    border-color: var(--c-brand);
}
