/* ---------------------------------------------------------------------------
 * bento-variant.css — styling for the variant target selector.
 *
 * Loaded via HTML_EXTRA_STYLESHEET after doxygen-awesome.css,
 * doxygen-awesome-sidebar-only.css and bento-lang.css, so every value below
 * reads the theme's own custom properties. tools/doxygen-awesome/* is
 * vendored and READ-ONLY — nothing here edits it.
 *
 * WHY A ROW OF ITS OWN, and not beside the pill on the search row.
 * ------------------------------------------------------------------------
 * The header column in the sidebar-only layout is a FIXED
 * --side-nav-fixed-width (335px) and `#top` clips anything past it. The
 * measured cost of the two labels at the theme's own 12px/600 face is
 * "ModusToolbox" 85px and "ModusToolbox & µPython" 150px; a native select
 * adds ~26px of padding and arrow. Putting a 176px control on the search row
 * beside the 68px language pill leaves the search box 76px — an unusable
 * input. So the selector takes the row ABOVE the search box, full column
 * width, and the search row keeps exactly the geometry bento-lang.css
 * measured for it. Nothing in that file changes.
 *
 * The header therefore needs one more row of height. --top-height is the
 * theme's own variable and every dependent measurement is derived from it
 * (#side-nav top and height, #doc-content padding-top), so raising it here is
 * the whole adjustment — scoped to `html.bento-variant-on`, the class
 * bento-variant.js sets ONLY when it actually inserted a selector. On a
 * packaged single-variant tree the class is absent and the header keeps the
 * height it has today, to the pixel.
 * ------------------------------------------------------------------------ */

html {
    /* One selector row: the control plus the gap under it. */
    --bento-variant-row: calc(var(--searchbar-height) + var(--spacing-small));
}

/* The sidebar-only layout pins the header to --top-height (120px) and clips
   it with overflow:hidden; #side-nav and #doc-content are positioned from the
   same variable. Adding a row without raising it cuts the search box off.
   Scoped to the class bento-variant.js sets only when it actually installed
   the control, so a single-variant package keeps the original height. */
@media screen and (min-width: 768px) {
    html.bento-variant-on {
        --top-height: calc(120px + var(--bento-variant-row));
    }
}

bento-variant-switch {
    display: block;
    box-sizing: border-box;
    margin: 0 0 var(--spacing-small) 0;
    /* Sits above the search box, which is inset by --spacing-medium on both
       sides in this layout; line the two up. */
    width: 100%;
}

/* Both menu bars lay their search row out with flex, so a block child is a
   flex ITEM and would sit beside the search box, not above it (measured:
   the search box landed at x=325 in a 335px column). The selector claims the
   whole line and the row wraps under it. */
html.bento-variant-on #searchBoxPos1,
html.bento-variant-on #main-menu > li#searchBoxPos2 {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
}

html.bento-variant-on #searchBoxPos1 > bento-variant-switch,
html.bento-variant-on #main-menu > li#searchBoxPos2 > bento-variant-switch {
    flex: 0 0 100%;
}

/* ---------------------------------------------------------------------------
 * The control: two segments, both real links, identical in shape to the
 * language pill. It was a <details> dropdown of anchors; that opened and
 * navigated correctly in Chrome but rendered oversized and clipped in Safari,
 * and every fix traded one layout surprise for another. A pill has no open
 * state, no floating panel, and no state that can change the header's height,
 * so there is nothing left to go wrong. The full package name rides in the
 * title attribute; the segments carry the short forms.
 * ------------------------------------------------------------------------ */

bento-variant-switch {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    /* width:auto UNSETS the `width: 100%` set further up for the sidebar
       position, where the switch lines up with the search box. Without this
       the switch keeps filling its parent wherever it is moved to: in the site
       header it took the whole controls slot, was then pushed right by the
       language pill beside it, and hung 60px past the right edge of the page
       at every viewport width. Measured by forcing the slot to 320px and
       watching the switch grow to 320px with it. */
    width: auto;
}

.bento-variant-pill {
    display: inline-flex;
    align-items: stretch;
    box-sizing: border-box;
    height: var(--searchbar-height);
    padding: 2px;
    border: 1px solid var(--separator-color);
    border-radius: var(--searchbar-border-radius);
    background: none;
    overflow: hidden;
    user-select: none;
}

/* Nothing here may change a metric on hover or focus: the control sits in a
   fixed-height header row, and a size change there reflows the page. Colour
   and opacity only. */
a.bento-variant-seg {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    padding: 0 10px;
    border-radius: var(--searchbar-border-radius);
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    /* Both halves are set explicitly rather than through the theme tokens.
       --page-foreground-color at .55 opacity read as a disabled control, and
       the selected half took --on-primary-color, which on the dark theme is
       close enough to --primary-color that the label vanished into its own
       background - the switch looked like a blue blob with the label of the
       OTHER half beside it. */
    color: var(--page-foreground-color);
    opacity: .72;
    transition: background-color var(--animation-duration) ease-in-out,
                color var(--animation-duration) ease-in-out,
                opacity var(--animation-duration) ease-in-out;
}

a.bento-variant-seg:hover,
a.bento-variant-seg:focus,
a.bento-variant-seg:focus-visible {
    text-decoration: none;
    opacity: .9;
}

a.bento-variant-seg.bento-variant-seg-current {
    background-color: var(--primary-color);
    color: #fff;                 /* never --on-primary-color; see above */
    opacity: 1;
}

/* No theme guard here. This site follows the system through
   prefers-color-scheme and sets no .dark-mode class, so an
   `html:not(.dark-mode)` rule matches on the DARK theme as well and paints the
   label near-black on near-black. --page-foreground-color is already correct
   in both themes; the colours are stated in bento-siteheader.css, where the
   !important that beats doxygen's a:link rule also lives. */

/* The page has no counterpart in the other package yet: the jump lands on
   that package's front page. Dotted underline adds no height. */
a.bento-variant-seg.bento-variant-seg-fallback {
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}

/* ---------------------------------------------------------------------------
 * MOBILE HEADER HEIGHT (<= 767px) — the other half of the overprint fix.
 *
 * bento-lang.css now sizes the search box to the row it is actually in, so the
 * language pill fits beside it and the row is TWO lines deep, not three:
 *
 *     line 1   the variant selector (flex: 0 0 100%, below)
 *     line 2   the search box + the TH|EN pill
 *
 * That is still one line more than the header has room for. #searchBoxPos1 is
 * absolutely positioned (doxygen.css:2172) at top:3px, so it contributes
 * nothing to the flow and #main-nav-mobile stays at the 36px its hamburger
 * gives it — which is why the extra lines were painted over the article <h1>
 * instead of pushing it down. Nothing below 768px reads --top-height (that is
 * the sidebar-only desktop branch), so the height has to be given to the flow
 * box directly.
 *
 * The arithmetic is the theme's own tokens, not constants:
 *     3px                     the row's own top offset
 *   + --bento-variant-row     the selector line   (33 + 5 = 38px)
 *   + --searchbar-height      the search line     (33px; the theme zeroes
 *                             #MSearchBox's margins in this branch)
 *   + --spacing-medium        breathing room above the rule
 *   = 84px
 *
 * Scoped to html.bento-variant-on: with no selector installed the row is one
 * line and the 36px header is already correct — a single-variant package keeps
 * the header it has today, to the pixel.
 * ------------------------------------------------------------------------ */
@media screen and (max-width: 767px) {
    html.bento-variant-on #main-nav-mobile {
        min-height: calc(3px
                         + var(--bento-variant-row)
                         + var(--searchbar-height)
                         + var(--spacing-medium));
    }
}

/* ---------------------------------------------------------------------------
 * READING WIDTH between 768px and 1200px.
 *
 * Measured on group__a1__first__build.html before this block: at 768px the
 * article was 250px — 33% of the window — while the two navigation rails
 * together took 68% of it, and the <h1> broke over five lines. Neither rail
 * yields on its own: doxygen-awesome-sidebar-only.css:34 pins #side-nav with
 * min-width AND max-width to --side-nav-fixed-width, and navtree.css gives
 * #page-nav a hard width. The only rule that drops either is at
 * max-width: 767px — one pixel below the worst case.
 *
 * Two thresholds, both derived rather than picked:
 *
 * 1200px — the outline rail returns here and nowhere lower. A 600px article
 *   (the narrowest measure that still reads as prose at this font size) plus
 *   the 335px sidebar plus the 250px rail needs 1185px, so 1200 is the first
 *   round width at which all three fit. Below it the rail is the thing to
 *   spend: it is a duplicate of headings the article already carries, and
 *   #nav-tree still gives the reader every one of them.
 *
 * 768px..1199px — the sidebar earns its width back as the window allows,
 *   instead of jumping at a breakpoint: clamp(260px, 33vw, 335px) is 260px at
 *   768, 297px at 900, and back to the theme's own 335px from 1015px up, which
 *   is below 1200 — so there is NO step at the rail's threshold, only the rail
 *   appearing. 260px is the floor because bento-lang.css spends
 *   --bento-lang-reserve (73px) and the theme spends 2 * --spacing-medium plus
 *   65px of furniture out of that same column: at 260px the search FIELD is
 *   still 102px, and shrinking it to nothing was a previous bug.
 *
 * Resulting article width (measured, mtb-mpy tutorial chapter):
 *     768  250 -> 508      1024  506 -> 689      1280  762 -> 762
 *     900  382 -> 603      1199  506 -> 864      1600 1082 -> 1082
 * ------------------------------------------------------------------------ */
@media screen and (max-width: 1199px) {
    #page-nav {
        display: none;
    }
}

@media screen and (min-width: 768px) and (max-width: 1199px) {
    html {
        --side-nav-fixed-width: clamp(260px, 33vw, 335px);
    }

    /* sidebar-only pins this to a hardcoded left: 300px, which is outside a
       260px column — it would float over the article. Derive it instead. */
    #nav-sync {
        left: calc(var(--side-nav-fixed-width) - 35px);
    }

    /* #projectname is white-space: nowrap inside a #top that is exactly
       --side-nav-fixed-width wide with overflow: hidden, so narrowing the
       column cut the product name ("SDK for TESAIoT Dev Ki|t" at 768px).
       The title tracks the column instead: clamp() reaches the theme's own
       22px at ~1000px, which is where the sidebar itself is back to 335px, so
       above that nothing about the header has changed. */
    html {
        --title-font-size: clamp(17px, 2.2vw, 22px);
    }
}

/* ---------------------------------------------------------------------------
 * WIDE TABLES SCROLL INSIDE THEMSELVES.
 *
 * div.contents has overflow-x: visible and the document does not scroll
 * horizontally, so anything wider than the article was not merely awkward —
 * it was CLIPPED AND UNREACHABLE BY ANY GESTURE. Measured on
 * group__peripherals__quickref: 269px of table lost at 768px, 155px at 390px,
 * and the column that goes over the edge is the file:line citation column,
 * which is the reason that page exists.
 *
 * The fix gives the table its own scroll region: the TABLE becomes a block
 * that fills the measure and clips with overflow-x:auto, and its TBODY becomes
 * a real table at width:max-content inside it. The excess then scrolls instead
 * of being cut. The whole page is deliberately NOT made to scroll sideways —
 * that would take the headings and the prose with it.
 *
 * The same treatment covers table.directory, the tree the reference index
 * pages (topics, files, annotated) are built from: measured at 390px on
 * topics.html its entries run past the viewport exactly the same way.
 *
 * Only prose tables. table.memberdecls is doxygen's declaration table; it
 * wraps rather than overflowing, it is the spine of every API page, and
 * turning it into a block box would change the layout of 128 pages to fix
 * nothing.
 * ------------------------------------------------------------------------ */
/* SPECIFICITY, because it is not obvious and it is the whole reason the
   selectors below are this long. doxygen-awesome.css:1868 already styles these
   tables — `.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable)
   :not(.memname)` — and :not() carries the specificity of its argument, so
   that selector is (0,5,1) and its full-bleed sibling at :1874 is (0,6,1). A
   plain `div.contents table.markdownTable` is (0,2,2) and loses to both; the
   display and max-width would simply not apply. Repeating the theme's own
   :not() chain puts these at (0,7,2), which wins on the merits rather than by
   !important. If the vendored theme's chain changes, this has to change with
   it — that is the cost of not being allowed to edit it. */
div.contents table.markdownTable:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex),
div.contents table.doxtable:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex),
div.contents table.params:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex),
div.contents table.directory:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) {
    display: block;
    overflow-x: auto;
    /* deliberately NO width or max-width: the theme already caps these at 100%
       (:1868) and gives a table that IS a direct child of div.contents a
       -16px/+32px full-bleed (:1874). Restating either here would win on
       specificity and quietly move every wide table 16px right of where it
       sits today. Auto width fills whatever the theme allowed. */
}

/* The TBODY has to become a real table box again, and this is the part that
   took two attempts to get right.
     - Left alone, it stays the theme's `display:inline-block; max-width:100%`
       (doxygen-awesome.css:1868). Measured: the cells then overflow the tbody
       but Chrome does NOT count that overflow in the table's scrollable area —
       scrollWidth == clientWidth — so the scroll container above it scrolls
       nothing and the content is still cut. 631px of the quick-reference page
       still sat off-screen at 390px with only the table rule applied.
     - Given `width: max-content` it scrolls correctly, but it also stops
       compressing: tables that fit perfectly today (both tables on the front
       page at 1600px) started demanding a scroll they never needed, and the
       last column left the article.
   `width: auto` is the table algorithm's own answer and gives both:
   max(min-content, min(max-content, available)). It fills the measure and
   wraps exactly as it does today whenever it can, and when the columns cannot
   be squeezed any further it takes its min-content width and the excess
   becomes scroll instead of clipping. min-width keeps a short table filling
   the measure; max-width:none is what lifts the theme's cap. */
div.contents table.markdownTable:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) > tbody,
div.contents table.doxtable:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) > tbody,
div.contents table.params:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) > tbody,
div.contents table.directory:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) > tbody {
    display: table;
    width: auto;
    max-width: none;
    min-width: 100%;
}

/* Code listings had the same disease from doxygen-awesome.css:1425's
   `overflow: hidden` — a long line was cut at the article's edge with no way
   to reach the rest. Scroll it. */
div.fragment,
pre.fragment {
    overflow-x: auto;
}

/* A path in inline code ran past the viewport and was unreadable — at 390px
   the quick-reference page painted `bento_libs/claw/common/shared/include/…`
   out to x=545 in a 390px window, and the page does not scroll sideways.
   `overflow-wrap: anywhere` ALONE does nothing here, which is the whole
   subtlety: doxygen.css:378 sets `span.tt { white-space: pre }`, and pre
   forbids every line break, so there is no break opportunity for overflow-wrap
   to take. pre-wrap keeps the significant spaces inside a code chip and allows
   wrapping; overflow-wrap then breaks the one long token; word-break: normal
   keeps ordinary prose words whole. Measured after: div.contents overflows by
   0px at 390px on both pages. */
code,
span.tt {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    word-break: normal;
}

/* ---------------------------------------------------------------------------
 * THE OUTLINE RAIL: wrap the labels instead of cutting them.
 *
 * doxygen-awesome.css:1358 makes each entry an inline-block with no wrapping
 * and no truncation, inside a 250px rail whose only overflow affordance is a
 * horizontal scroll nobody will find. At 1600px entries were reaching x=1615
 * in a 1600px viewport. These headings are long by design ("Step 0 — Obtain
 * the MicroPython port", "Appendix X — Traps and anti-patterns"), so wrapping
 * is right and an ellipsis would not be: a truncated label is no more use than
 * a clipped one.
 * ------------------------------------------------------------------------ */
#page-nav ul.page-outline li a {
    /* NOT display:block. navtree.js builds each entry as
       <div class="item"><span class="arrow" style="padding-left:Npx"><a>,
       and that inline padding on the arrow is the ONLY thing carrying the
       outline's nesting. A block anchor drops to its own line at the left
       edge, leaving the indent behind on the arrow above it, and the rail
       flattens into one level. inline-block keeps the label beside its arrow;
       white-space:normal is what actually buys the wrapping. */
    display: inline-block;
    vertical-align: top;
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
    /* 1.5 is leading WITHIN one wrapped entry; the theme's own
       calc(2 * --toc-font-size) was row pitch for entries that could never
       wrap, and reusing it here would space the two lines of one heading as
       far apart as two different headings. The padding puts the pitch back
       between entries. */
    line-height: 1.5;
    /* padding-block only. The shorthand `padding: Npx 0` also sets
       padding-left to 0, and that is where doxygen-awesome puts the outline's
       indentation — writing it flattened every level of the rail into one
       list, so a reader could no longer see which heading sat under which. */
    padding-block: 1px;
}

/* ---------------------------------------------------------------------------
 * SECTION HUBS ARE A TABLE OF CONTENTS, NOT A CODE LISTING.
 *
 * doxygen puts a group's sub-topic list in <table class="memberdecls">, and
 * doxygen.css:747 sets a monospace face on every memitem row of such a table.
 * Correct for members; wrong for the chapter titles on every section hub, so
 * the Appendices page read as a code listing. The :has() test picks out
 * exactly the sub-topic table — it is the only memberdecls table headed by
 * #header-groups — and leaves every declaration table alone.
 * ------------------------------------------------------------------------ */
table.memberdecls:has(h2#header-groups) td.memItemRight a.el,
table.memberdecls:has(h2#header-groups) td.memItemRight,
table.memberdecls:has(h2#header-groups) td.memItemLeft {
    font-family: var(--font-family);
    font-size: var(--page-font-size) !important;
}
