/*
 * Copyright (C) 2004-2026 Metaphonic Labs
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General
 * Public License along with this program; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * panes.css -- the tiled layout, and nothing else.
 *
 * Its own file beside style.css, because none of it applies until
 * panes.js has put `tiled' on the body: everything here is under that
 * class or inside the layout's own elements, so a page with the tiler off
 * is styled by style.css alone. That is the same claim panes.js makes
 * about the markup, made about the stylesheet.
 *
 * The tree is nested flex boxes. A split is a box with a direction, its
 * children carry a fraction as `flex-grow' and a minimum as `min-width',
 * and the browser does the arithmetic -- there is no measuring here.
 *
 * WHAT IS NOT HERE is what a page puts *in* a pane. That a <details>
 * adopted into one has to become a column is this file's to say -- it is
 * the price of adopting the document, and every page that does pays it.
 * That the piano roll stretches and the keys do not is the page's, and
 * it moved to style.css: no stylesheet shipped with a tiler can know
 * which of somebody's boxes is the one that wants the room.
 *
 * THE COLORS are read under this file's own names -- `--pane-line' and
 * the rest -- each with a fallback, so a page that maps nothing still
 * gets a layout it can see and a page that maps them gets its own
 * theme. Reading `--line' directly would be worse than reading nothing:
 * a page that has a `--line' meaning something else would get a layout
 * quietly wearing the wrong color, which is the failure nobody
 * investigates.
 */

/* The element the page hands to createPanes, which puts this class on it
   -- so these rules key on something the module knows it has rather than
   on the id one page happened to choose. Empty until there is a layout,
   and nothing in the document should know it is there. */
.panesroot:empty { display: none; }

/*
 * The page, tiled: the chrome across the top at whatever height it wants,
 * and the layout taking the rest of the window.
 *
 * `100dvh' rather than `100vh' because a mobile browser's toolbars come
 * and go, and a layout that is a toolbar taller than the window has its
 * bottom row under one. Nothing tiles on a phone, but a narrow laptop
 * window crossing the threshold is the same arithmetic.
 *
 * And `--pane-height' over it, because `dvh' accounts for retracting
 * browser chrome and nothing else: a page with a text box at the bottom
 * has the on-screen keyboard drawn over it, and the only thing that
 * reports the box actually visible is `visualViewport'. A page that
 * tracks it sets this to what it found.
 */
body.tiled
{
    max-width: none;
    margin: 0;
    padding: 0.6em 0.8em;
    height: var(--pane-height, 100dvh);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* The drawer above, the layout under it. */
body.tiled .panesroot
{
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    position: relative;
}

body.tiled .panesroot > .panebox,
body.tiled .panesroot > .paneleaf { flex: 1 1 auto; min-height: 0; }

/* ---- the tree ----
 *
 * A split is a flex box with a direction; its children carry their
 * fraction as `flex-grow' over a basis of nothing, so what each is worth
 * is its share of what there is and the browser works out the rest. The
 * minimum is on the child rather than on the pane inside it, because the
 * child is what a divider has to refuse to shrink.
 */

.panebox, .paneleaf
{
    display: flex;
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
}

.panebox[data-dir="row"] { flex-direction: row; }
.panebox[data-dir="col"] { flex-direction: column; }

/* A leaf is its strip of tabs and the pane under them. */
.paneleaf { flex-direction: column; }

/* The divider. As thick as `--pane-split', which panes.js writes onto
   the root from the number its own arithmetic uses -- what refuses a
   drag and what is drawn are one number now rather than two asked to
   agree. A hit area that does not have to be aimed at, and a line down
   the middle that does not move. */
.panesplit
{
    flex: 0 0 var(--pane-split, 6px);
    position: relative;
    background: transparent;
    border: 0;
    padding: 0;
}

.panebox[data-dir="row"] > .panesplit { cursor: col-resize; }
.panebox[data-dir="col"] > .panesplit { cursor: row-resize; }

.panesplit::after
{
    content: "";
    position: absolute;
    inset: 0;
    background: var(--pane-line, #dcdcdc);
    border-radius: 1px;
}

.panebox[data-dir="row"] > .panesplit::after { inset: 0 2px; }
.panebox[data-dir="col"] > .panesplit::after { inset: 2px 0; }

.panesplit:hover::after, .panesplit:focus-visible::after
{
    background: var(--pane-held, #5050ff);
}

.panesplit:focus-visible { outline: none; }

/* ---- a pane ---- */

.pane
{
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    border: 1px solid var(--pane-line, #dcdcdc);
    border-radius: 4px;
    background: var(--pane-bg, #ffffff);
    overflow: hidden;
}

/* What was a block in a document is a column in a pane: the box that
   wants the room takes it, and the rows around it keep their height.
   Which box that is is said below rather than guessed at. */
.panebody > details,
.panebody > section
{
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0;
}

/* A <details> keeps what it discloses in a box of its own, and that box
   is the flex item -- so the column has to go through it, or the text
   area inside is laid out against nothing and comes out three rows tall.
   An engine without ::details-content slots the children straight into
   the rule above and does not need this one; the two together are every
   engine, which is why both are here. */
.panebody > details::details-content
{
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* A pane whose mode is not up.
 *
 * The attribute is this module's own (`OFF' in panes.js) rather than
 * `hidden', which is a word most pages are already using for something
 * else -- so the element has to be hidden here, since nothing else now
 * does it. Both rules: the element goes, whether or not there is a
 * layout, and the pane around it goes with it rather than staying as an
 * empty bordered box. */
[data-pane-off] { display: none !important; }

.pane:has(> .panebody > [data-pane-off]) { display: none; }

/* ---- the tabs ----
 *
 * One tab is a pane's header; several are a choice, and the same strip
 * either way. Which is what makes a <details> able to hand its
 * disclosure over to it: the pane always has a header to be one.
 */
.panetabs
{
    flex: 0 0 auto;
    display: flex;
    background: var(--pane-panel, #f4f4f4);
    border-bottom: 1px solid var(--pane-line, #dcdcdc);
    overflow: hidden;
}

/* A tab and the cross that closes it are one item of the strip, so the
   line under the tab in front runs under both of them and the border
   between panes falls after the cross rather than before it. */
.panetabwrap
{
    flex: 0 1 auto;
    min-width: 0;
    display: flex;
    align-items: stretch;
    border-right: 1px solid var(--pane-line, #dcdcdc);
    border-bottom: 2px solid transparent;
}

.panetabwrap:has(> .panetab[aria-selected="true"])
{
    background: var(--pane-bg, #ffffff);
    border-bottom-color: var(--pane-held, #5050ff);
}

.panetab
{
    flex: 0 1 auto;
    min-width: 0;
    padding: 0.25em 0.2em 0.25em 0.7em;
    font: inherit;
    font-size: 0.85em;
    color: var(--pane-dim, #666666);
    background: transparent;
    border: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
    touch-action: none;         /* a tab drags; it does not scroll */
}

.panetab[aria-selected="true"] { color: var(--pane-fg, #202020); }

.panetab.panedragging { opacity: 0.5; }

/* Closing a pane puts it in the drawer, so the cross is a quiet one: on
   the tab in front, and on whichever tab the pointer or the focus is at.
   Hidden by `visibility' and not by `display', or a strip of them would
   change width under the pointer and the tab being aimed at would move
   out from under it. */
.paneshut
{
    flex: 0 0 auto;
    padding: 0 0.45em 0 0.2em;
    font: inherit;
    font-size: 0.85em;
    line-height: 1;
    color: var(--pane-dim, #666666);
    background: transparent;
    border: 0;
    cursor: pointer;
    visibility: hidden;
}

.panetabwrap:hover > .paneshut,
.panetabwrap:focus-within > .paneshut,
.panetab[aria-selected="true"] + .paneshut { visibility: visible; }

.paneshut:hover { color: var(--pane-fg, #202020); }

/* ---- the drawer ----
 *
 * The panes no leaf has room for. A closed pane is put away and not lost,
 * so this is a list of them and not a list of things to be made again.
 */
.panedrawer
{
    flex: 0 0 auto;
    display: flex;
    gap: 0.3em;
    flex-wrap: wrap;
    margin-bottom: 0.4em;
}

/* What the row is, for somebody who has just made it appear by closing
   a pane and is looking for where it went. */
.panedrawerlabel
{
    align-self: center;
    font-size: 0.85em;
    color: var(--pane-dim, #666666);
}

.paneclosed
{
    padding: 0.15em 0.6em;
    font: inherit;
    font-size: 0.85em;
    color: var(--pane-dim, #666666);
    background: var(--pane-panel, #f4f4f4);
    border: 1px dashed var(--pane-line, #dcdcdc);
    border-radius: 3px;
    cursor: pointer;
    touch-action: none;
}

.paneclosed:hover, .panetab:hover { color: var(--pane-fg, #202020); }

/* A layout with every pane closed out of it, which is a box with nothing
   in it and needs to say that it is empty rather than broken. */
.paneempty
{
    margin: auto;
    padding: 1em;
    font-size: 0.9em;
    color: var(--pane-dim, #666666);
    text-align: center;
}

/* Where a dragged tab would land, over the pane it would land in. */
.panedrop
{
    position: absolute;
    z-index: 3;
    pointer-events: none;
    background: color-mix(in srgb, var(--pane-held, #5050ff) 20%, transparent);
    border: 2px solid var(--pane-held, #5050ff);
    border-radius: 4px;
}

.panebody
{
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    padding: 0 0.6em 0.6em;
    display: flex;
    flex-direction: column;
}

/* A pane is a query container, so a page can lay its own boxes out
   against the room this one has rather than against the window's. That
   is the tiler offering a question rather than answering one:
   style.css's own rules about what wraps inside a pane are what make
   use of it. */
body.tiled .panebody { container-type: inline-size; }

/*
 * Over every pane: where a popover goes, now that the pane it belongs
 * beside is a box that scrolls and would clip it.
 *
 * Absolute at the document's origin and of no size, so an absolutely
 * positioned child of it resolves against the same containing block the
 * body gave it -- which is what lets composerview.js and nodeview.js
 * place these in page coordinates exactly as they did.
 */
.paneoverlay
{
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 0;
}
