/* =============================================================================
 * Atlas Cloud Tools — the app bar
 *
 * CANONICAL COPY. Each tool carries a byte-identical copy;
 * scripts\Sync-AtlasTokens.ps1 copies it out and -Check fails the build if any
 * copy has drifted. Edit here, never in a copy.
 *
 * WHY THIS IS ITS OWN FILE. The bar is the one component every tool draws, and
 * it is the one that kept drifting. Its rules used to live in atlas-theme.css,
 * which only three of the six tools take — the theme restyles Bootstrap's
 * classes and BIReports and Statements V2 have no Bootstrap — so a fix applied
 * there reached the Blazor tools and left the two React ones behind. That is
 * how BIReports ended up with a bare-text Return to Tools and light page
 * buttons in the strip while Statements, one click away, had padded pills and
 * Midnight ones.
 *
 * So: the bar's chrome is separated from the Bootstrap repaint and every tool
 * takes it. Nothing Bootstrap-specific belongs in here, and no tool may
 * restate these rules locally — a second copy is what produced the drift.
 *
 * Class names differ between the React and Blazor tools for historical
 * reasons; both spellings are matched here rather than renamed, because
 * renaming them is a markup change and this is a stylesheet.
 *
 * See UnifiedLogin/docs/atlas-tools-style-guide.md §3 (ACT-70).
 * ========================================================================== */

/* --- The bar's text controls -------------------------------------------------
 * Return to Tools, and the caret that opens the user menu.
 *
 * Statements' .app-bar__link treatment, which is the one to keep: the control
 * fills with the shell's own field tint and its label brightens. BIReports and
 * the Blazor tools only changed the text colour, so the target was invisible
 * until the pointer was already on the words, and nothing told you the caret
 * was a control at all.
 *
 * The hover state is the shell's field tint plus full-strength ink — the same
 * two tokens the in-bar tabs use. */
.return-to-tools-link,
.app-bar__link,
.user-dropdown .dropdown-icon {
    font-size: var(--font-size-control);
    color: var(--color-shell-fg-dim);
    text-decoration: none;
    white-space: nowrap;
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    transition: background 120ms, color 120ms;
}

/* Return to Tools is a peer of the user block and the tenant picker, not a
   subordinate of them, so it rests at the same strength they do. The caret
   stays dim: it is a glyph attached to the name it opens, not a label of its
   own.
 *
 * `a…:any-link` rather than the bare class, and this is the whole reason the
 * link looked wrong in the first place. It is an anchor sitting inside each
 * app's own page shell, so a page-level link rule reaches it: TV Dashboards
 * has `.page-shell a { color: var(--color-link) }` at (0,1,1), which outscored
 * the bare class here and painted the label Wet Asphalt — the DARK shell
 * background colour — on the dark bar. The label was not dim, it was very
 * nearly invisible, and it differed per app depending on what that app's
 * stylesheet happened to say about anchors.
 *
 * Element plus class plus pseudo-class is (0,2,1), which no app-level `a` rule
 * reaches, so the bar now looks the same in all six tools whatever they do to
 * their own links. */
a.return-to-tools-link:any-link,
a.app-bar__link:any-link { color: var(--color-shell-fg); }

/* Same specificity problem, same answer: a page-level `a:hover` would otherwise
   repaint the label mid-hover. */
a.return-to-tools-link:any-link:hover,
a.app-bar__link:any-link:hover,
.user-dropdown:hover .dropdown-icon,
.user-dropdown:focus-within .dropdown-icon {
    background: var(--color-shell-field-bg);
    color: var(--color-shell-fg);
}

/* The tint belongs to the control whether or not the anchor carries an href. */
.return-to-tools-link:hover,
.app-bar__link:hover { background: var(--color-shell-field-bg); }

/* The caret is a glyph, not a word, so it keeps its own size and a squarer box. */
.user-dropdown .dropdown-icon {
    font-size: 0.6rem;
    padding: 8px 10px;
}

/* A TAB IN THE BAR IS FLAT, LIKE THE LINK BESIDE IT.
 *
 * Statements' Generate and Settings tabs declared `background: transparent;
 * border: none` on the fluent-button HOST, which paints nothing — the box is
 * drawn by ::part(control) inside the shadow root — so the two tabs came out as
 * light grey, silver-edged buttons stuck on the dark bar while every other
 * thing in every other bar was flat. Same shape as .app-bar__link and the
 * user-menu rows: the tint on hover IS the affordance, and the current one is
 * the heavier tint. */
.app-bar__tab::part(control) {
    background: none;
    border: none;
    box-shadow: none;
    color: var(--color-shell-fg-dim);
    padding: var(--control-pad-y) var(--control-pad-x-tight);
    border-radius: var(--radius);
    font-weight: 500;
}

.app-bar__tab:hover::part(control) {
    background: var(--color-shell-field-bg);
    color: var(--color-shell-fg);
    border: none;
}

.app-bar__tab.is-active::part(control) {
    background: var(--color-shell-field-bg-hover);
    color: var(--color-shell-fg);
    font-weight: 600;
}

/* THE CARET IS AN ICON, WHATEVER ELEMENT IT IS.
 *
 * The three Blazor tools render it as <span slot="heading">; BIReports and the
 * portal render a real <button>, because their menu component needs something
 * focusable to hang the trigger on. Same class, same glyph, same place in the
 * bar — and the two <button> ones came out as Clouds-filled, silver-edged boxes
 * on the dark bar, because atlas-theme.css paints every <button> that way and
 * nothing here said otherwise. One bar, two different carets, and it was the
 * first thing anyone noticed flipping between the tools.
 *
 * An ICON has no fill, no edge and no shadow — the platform's own taxonomy. The
 * hover tint above is the whole affordance. Stated on .dropdown-icon rather
 * than on `button.dropdown-icon` so it holds for the span, the button, and
 * whatever the next tool reaches for.
 *
 * Scoped to the bar as well as bare, and that is not belt-and-braces: the theme
 * gives every control IN the bar a field tint with `.app-header button` (0,1,1),
 * which outranks a bare `.dropdown-icon` (0,1,0). The <button> caret came out
 * tinted at rest while the <span> next to it was clear — the same mismatch one
 * layer down. `.app-header .dropdown-icon` is (0,2,0) and settles it. */
.app-header .dropdown-icon,
.header-inner .dropdown-icon,
.header-wrapper .dropdown-icon,
.app-bar .dropdown-icon,
.dropdown-icon {
    background: none;
    border: none;
    box-shadow: none;
    min-height: 0;
    color: var(--color-shell-fg-dim);
    cursor: pointer;
    border-radius: var(--radius);
    line-height: 1;
}

/* --- THE BAR ALIGNS WITH THE CONTENT ---------------------------------------
 * The content column stops at --content-max-w and is centred; leaving the bar's
 * row full-bleed put the logo hard against the window edge while the first
 * heading under it started hundreds of pixels inboard, and the gap changed with
 * every window size. Same cap, same centring, same 2em inset — so the logo, the
 * tab strip and every page heading share one left rule. The BAND still spans
 * the window; only its row is bounded. */
/* --- THE BAR'S LAYOUT ------------------------------------------------------
 * THREE COLUMNS, NOT A CENTRED ABSOLUTE. The tenant picker used to be
 * position: absolute at left: 50%, which centres it on the WINDOW and takes it
 * out of the flow — so it knew nothing about the brand on its left or the user
 * block on its right, and as soon as the window narrowed it simply drew on top
 * of them. Measured at 760px: the picker overlapped Return to Tools by 88px,
 * in every tool, and BIReports' report buttons (fixed at left: 230px and
 * right: 300px) crossed the wordmark and the link as well.
 *
 * A grid of minmax(0, 1fr) auto minmax(0, 1fr) centres the middle cell exactly
 * as the absolute did — the two side columns are always equal — but the cells
 * are real boxes that cannot be walked over. When there is not enough room the
 * side columns shrink and their contents ellipsis, which is a legible failure
 * instead of overlapping text.
 *
 * minmax(0, 1fr) rather than 1fr: a grid track's default minimum is its
 * content's min-content width, which for a long company name or user name is
 * wider than the space available — the track refuses to shrink and pushes the
 * layout wide. The explicit 0 minimum is what lets the ellipsis rules below
 * actually take effect.
 *
 * Columns are assigned explicitly rather than by source order, so a tool with
 * no tenant picker does not slide its user block into the centre cell.
 *
 * The bar also ALIGNS WITH THE CONTENT: the content column stops at
 * --content-max-w and is centred, and leaving the bar's row full-bleed put the
 * logo hard against the window edge while the first heading under it started
 * hundreds of pixels inboard. The BAND still spans the window; only its row is
 * bounded. */
.header-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 12px;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 0 2em;
    position: relative;
    max-width: var(--content-max-w);
    margin-left: auto;
    margin-right: auto;
}

/* ALIGNED WITH justify-content, NEVER justify-self.
 *
 * justify-self: end looks like the obvious way to push the user block to the
 * right of its column, and it is a trap: it takes the item off `stretch`, so
 * the box is sized to its own max-content instead of to the track, and when
 * that is wider than the track the item simply hangs out of the column. It
 * measured 321px in a 221px track at 760px wide — a hundred pixels of user
 * block sitting on top of the tenant picker, which is the same overlap the
 * absolute positioning produced, one layer further in.
 *
 * Leaving each cell stretched and aligning INSIDE it with justify-content keeps
 * the box exactly one track wide, so its own children are the things that have
 * to give, and the ellipsis rules below are what gives. */
.header-left {
    grid-column: 1;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 1em;
    min-width: 0;
}

.company-selector-center {
    grid-column: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
}

.header-actions {
    grid-column: 3;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    min-width: 0;
}

/* The user block is the only thing in the right-hand cluster that may shrink.
   The link and the menu are controls: a half-width Return to Tools is not a
   smaller control, it is a broken one. */
.header-actions > .return-to-tools-link,
.header-actions > .user-dropdown { flex: 0 0 auto; }

/* THE TWO GAPS IN THE RIGHT-HAND CLUSTER, STATED ONCE.
 *
 * The flex gap above is 8px, and four apps then added their own margin on top of
 * it — 8px in ACH, Warranty and TV Dashboards, 16px in BIReports, nothing in
 * Statements. So the space between Return to Tools and the user's name was 16px
 * in three tools, 24px in one and 8px in another, which is exactly the kind of
 * difference you see when you flip between two of them and cannot name.
 *
 * 16px to the user block (ACH's, and the majority), and the caret against the
 * name: it is the same control as the name it drops from, and 8px of gap plus
 * its own 10px of padding read as a loose glyph floating near the corner.
 *
 * MARGINS, NOT gap, AND THAT IS THE POINT. A negative margin does not close a
 * flex gap when the row is justify-content: flex-end — the item does move, but
 * the row is anchored on its right edge, so everything BEFORE it slides right by
 * the same amount and every gap measures exactly what it did. It has to be per
 * pair, so the gap itself goes to zero and each pair states its own. */
.header-actions { gap: 0; }
.header-actions > * + * { margin-left: var(--space-3); }
.header-actions > .return-to-tools-link { margin-right: var(--space-3); }
.header-actions > .user-info + .user-dropdown { margin-left: var(--space-2); }

/* The menu itself, which had no platform definition at all — four apps each
   declared it, all four adding `margin-left: 4px`, and in the three Blazor tools
   it was SCOPED (.user-dropdown[b-xxxxxxx]), which outranks anything shared. A
   fourth source of space on the caret, on top of the flex gap, .user-info's old
   margin and the caret's own padding. */
.user-dropdown {
    position: relative;
    cursor: pointer;
}

/* --- ONE MENU, OPENING IN ONE PLACE ----------------------------------------
 * EVERY PANEL CLEARS THE BAR, rather than hanging 4px under whatever opened it.
 *
 * All three menus already dropped 4px below their TRIGGER, and that is why they
 * still did not line up: the trigger is a different box in each. A React
 * AtlasMenu resolves against .atlas-menu, which wraps the caret alone; a Blazor
 * accordion resolves against .user-dropdown, which wraps the heading; and the
 * two are different heights and sit at different heights inside a 57px bar. Four
 * pixels from three different boxes is three different places.
 *
 * So the panels stop being positioned against their trigger at all. The bar
 * neutralises the intermediate positioning and .header-inner — the content
 * column, which is already position: relative and spans the bar's full height —
 * becomes the containing block. top: 100% is then the bar's bottom edge in every
 * tool, and right: 0 is the content column's right edge, which is exactly where
 * the caret sits because the caret is the last item in .header-actions.
 *
 * THAT HOLDS ONLY FOR THE MENU AT THE BAR'S RIGHT EDGE. The user caret is the
 * last item in .header-actions, so the content column's right edge and the
 * caret's right edge are the same line. A menu that is NOT last — My Views,
 * portaled into the bar beside it — got the same right: 0 and landed a third of
 * a screen away from its trigger, under the user block.
 *
 * So an .atlas-menu in the bar anchors to ITSELF and stretches to the bar's
 * height. align-self: stretch is what keeps the reason above intact: top: 100%
 * is still the bar's bottom edge, not the trigger's, so every panel clears the
 * bar by the same amount whatever opened it. The button inside stays centred —
 * .atlas-menu is an inline-flex with align-items: center. */
.header-actions .atlas-menu { position: relative; align-self: stretch; }
.header-actions .user-dropdown { position: static; }

.header-actions .atlas-menu__panel,
.header-actions .user-dropdown-item::part(region),
.header-actions .app-bar__menu-item-host::part(region) {
    position: absolute;
    top: 100%;
    right: 0;
    left: auto;
    /* --popup-gap, like every other panel: the menu hangs off the bar's bottom
       edge. This was a hard-coded 4px, so the bar's menu sat further from what
       opened it than the Views menu two rows down. */
    margin-top: var(--popup-gap);
    /* A FLOOR AND A CEILING, NOT A FIXED WIDTH. width: 150px meant the panel
       could not grow for its own content: a saved view called "Collective
       Equipment Report" came out as "Collectiv…" in a menu with room to spare.
       min-width keeps the short menus from looking ragged, max-width stops one
       long name producing a panel half the bar wide, and between them the panel
       sizes to what is in it. */
    min-width: 150px;
    max-width: 320px;
    padding: 0;
}

/* ONE ROW, in all three. The rows were 36px with 8px 12px of padding in the
   React and Blazor menus and 30px with 0 8px in Statements', because Statements
   builds its rows from fluent-button and inherits the platform's flat-ROW
   padding — which is right for a report picker with forty entries in it and too
   tight for a four-item user menu. Stated here for the bar's menu only, so the
   list affordances elsewhere keep theirs. */
.header-actions .atlas-menu__item,
.header-actions .dropdown-item,
.header-actions .app-bar__menu-item::part(control) {
    padding: var(--space-3) var(--space-4);
    min-height: var(--menu-row-h);
}

/* The tenant picker's own box, which three of the six tools each declared in
   their app.css and the other three did without. */
.company-selector {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.company-selector form {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: 0;
}

/* No margin-right: the caret that follows is the same control as this block, and
   the space between them is the caret's own 10px of padding. The 8px that used
   to be here sat on top of the flex gap AND the padding, which is what made the
   glyph look detached from the name it belongs to. The gaps in this cluster are
   stated together above. */
.user-info {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    line-height: 1.2;
    flex: 0 1 auto;
    min-width: 0;
}

.header-brand {
    display: flex;
    align-items: center;
    text-decoration: none;
    min-width: 0;
}

/* The mark itself, which the bar was missing. The three tools that carry this
   header each sized it in their OWN stylesheet — Header.css in BIReports,
   MainLayout.razor.css in ACH Tools and Warranty — so the shared bar rendered an
   850px image anywhere the app sheet was not also loaded, and retuning it meant
   three edits. Same 24px, stated once, where the rest of the bar lives. */
.header-logo {
    height: 24px;
    width: auto;
    margin-right: var(--space-3);
}

/* WHAT GIVES WAY FIRST. Everything in the bar is one line, so the only way to
   fit a narrow window is for something to get shorter. The order is deliberate:
   the wordmark and the user's name truncate, because they are labels and a
   truncated label is still a label. The controls — the picker, the link, the
   menu — never shrink, because a half-width control is not usable. */
.header-brand h1,
.user-name,
.user-role {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    max-width: 100%;
}

/* WHAT THE TWO LINES LOOK LIKE, AND IT IS SAID HERE ONCE.
 *
 * This file already owned the user block's LAYOUT and its narrowing, but not its
 * paint — so each tool supplied that itself, or didn't. The result was four
 * different blocks from one component: the portal at weight 600 and 0.8rem on
 * flat white, Statements printing the company with no role at all, and the two
 * Blazor tools with no rule of their own falling back to whatever they
 * inherited. It is why the same corner of the same bar looked different in
 * every screenshot taken of it.
 *
 * The values are BIReports' (Header.css:131) — it is the gold standard and is
 * not modified to match anything, so the platform matches it. That file is React
 * and does not take this stylesheet, so the definition exists twice: IF EITHER
 * IS RETUNED, RETUNE BOTH.
 *
 * The second line is ALWAYS "Company - Role". A role the user cannot see is a
 * permission they cannot reason about when a screen refuses them something. */
.user-name {
    font-size: 0.9rem;
    color: var(--color-shell-fg);
    text-align: right;
}

.user-role {
    font-size: 0.7rem;
    color: var(--color-shell-fg-muted);
    font-weight: 300;
    text-align: right;
}

/* Page-level controls drawn INTO the bar by another component sit here, beside
   the brand, as real flow items. BIReports' Refresh Report and My Views used to
   be position: fixed at hard-coded offsets, which is why they crossed the
   wordmark the moment the window moved. */
.header-tools {
    display: flex;
    align-items: center;
    gap: 1em;
    min-width: 0;
}

/* A TOOLS SLOT HOLDS CONTROLS, SO IT DOES NOT SHRINK.
 * It was a flex item at the default flex-shrink: 1 with min-width: 0, which
 * means the SLOT collapses on demand while the button inside keeps its own
 * width — so the button simply drew outside its box and across Return to Tools.
 * That is not narrowing, it is overlapping, and it is the same class of mistake
 * as the position: fixed offsets this slot replaced. Controls never shrink;
 * what gives way is a label, below. */
.header-tools { flex: 0 0 auto; }

/* THE FLOOR. Truncation is the right answer until the truncated thing stops
   saying anything — measured at 700px, the company-and-role line was down to
   12px, which is one clipped letter and reads as a rendering fault rather than
   as a label. Past that point a label is dropped instead of shaved.

   Order is by what the label is worth: the wordmark and the role line go first
   (the wordmark is the same three words in every tool, and the role is on the
   user menu), then the user's name. The brand mark, the tenant picker, Return
   to Tools and the menu survive at any width — that is the set you need to see
   where you are and get somewhere else. */
/* Each label has its own point, measured rather than picked: the width at which
   what is left of it stops being worth the room. The role line is the longest
   string in the smallest type, so it is the first to stop reading — 92px of 122
   at 900 is still "MWN Consulting - …", 32px at 780 is not. */
@media (max-width: 820px) {
    .user-role { display: none; }
}

@media (max-width: 720px) {
    .header-brand h1 { display: none; }
    .header-inner { padding: 0 1em; gap: 8px; }
}

@media (max-width: 560px) {
    .user-info { display: none; }
}

/* --- A BUTTON PINNED OVER THE BAR FROM OUTSIDE IT ---------------------------
 * atlas-fluent.css inverts a button that sits in the bar — Midnight at rest,
 * the platform's steel blue on hover — and it does that by DESCENT, matching
 * fluent-button inside .app-header / .app-bar. That covers Statements' Generate
 * and Settings, which really are in the bar.
 *
 * BIReports' Refresh Report, Cancel and My Views are not. They are rendered by
 * the report viewer, inside <main>, and put in the strip with position: fixed —
 * so the bar-scoped rules never matched them and they kept the light Clouds
 * fill a button has on a page. Two tools, the same strip, two different
 * buttons.
 *
 * This is the same treatment matched on a CLASS instead of an ancestor, so a
 * control that is drawn into the bar from elsewhere is still a control in the
 * bar. It is deliberately the identical set of declarations — if the inversion
 * above is ever retuned, retune both.
 *
 * Fluent draws into a shadow root, so the fill has to be set on ::part(control);
 * a background on the host element is covered by the part and does nothing. */
fluent-button.app-bar__btn::part(control) {
    background: var(--color-action-ink);
    border-color: var(--color-action-ink);
    color: var(--color-action-hover-fg);
    box-shadow: none;
}

fluent-button.app-bar__btn:hover:not([disabled])::part(control) {
    background: var(--color-action-hover);
    border-color: var(--color-action-hover);
    color: var(--color-action-hover-fg);
}

fluent-button.app-bar__btn.is-on::part(control),
fluent-button.app-bar__btn.is-active::part(control),
fluent-button.app-bar__btn.active::part(control),
fluent-button.app-bar__btn[aria-pressed='true']::part(control),
fluent-button.app-bar__btn[aria-expanded='true']::part(control),
fluent-button.app-bar__btn[aria-current='page']::part(control) {
    background: var(--color-action-hover);
    border-color: var(--color-action-hover);
    color: var(--color-action-hover-fg);
    font-weight: 600;
}

fluent-button.app-bar__btn[disabled]::part(control),
fluent-button.app-bar__btn[disabled]:hover::part(control) {
    background: var(--color-action-ink);
    border-color: var(--color-action-ink);
    color: var(--color-shell-fg-muted);
}

/* A STATUS THE BUTTON REPORTS STILL OVERRIDES THE FILL. Refresh Report turns
   green when the dataset refreshed and amber when it failed, and Cancel is amber
   because cancelling is the destructive half of the pair. Those carry meaning,
   so they are not flattened into the bar's Midnight — they keep the status
   colour and take the bar's white label, which the light fill above would not
   have given them. */
fluent-button.app-bar__btn.is-status-success::part(control),
fluent-button.app-bar__btn.is-status-success[disabled]::part(control) {
    background: var(--color-success);
    border-color: var(--color-success);
    color: var(--color-on-dark);
}

fluent-button.app-bar__btn.is-status-error::part(control),
fluent-button.app-bar__btn.is-status-error[disabled]::part(control) {
    background: var(--color-warning);
    border-color: var(--color-warning);
    color: var(--color-on-dark);
}

fluent-button.app-bar__btn.is-status-danger::part(control) {
    background: var(--color-warning);
    border-color: var(--color-warning);
    color: var(--color-on-dark);
}

fluent-button.app-bar__btn.is-status-danger:hover::part(control) {
    background: var(--color-warning-hover);
    border-color: var(--color-warning-hover);
    color: var(--color-on-dark);
}


/* --- THE SHELL ITSELF ----------------------------------------------------------
 * ACT-87. This file already owned what sits INSIDE the bar — the brand, the
 * tools slot, the user block, the narrowing. The bar's own band, the footer and
 * the content column were defined per app: six copies of .app-header, six of
 * .app-footer, four each of .header-wrapper and .main-content-area. They agreed
 * in substance, except the portal's, which was written in literals (#1f2937,
 * white) and so could not follow a token when one moved.
 *
 * Values are BIReports' and ACH's, which already matched; the two hard numbers
 * they both spelled out (57px, 2.5rem) are the tokens that already held them.
 *
 * The Blazor tools carried these in MainLayout.razor.css — SCOPED css, which
 * compiles to .app-header[b-xxxxxxx] and outranks any shared rule. Deleting
 * them is what lets this file apply at all; a shared rule sitting under a
 * scoped one is the quietest kind of dead code. */
.header-wrapper {
    width: 100%;
    height: var(--app-bar-h);
    background-color: var(--color-shell-bg);
    position: sticky;
    top: 0;
    z-index: 1000;
    margin-bottom: 0;
    flex-shrink: 0;
}

/* --app-bar-inset-start: THE ONE THING AN APP MAY TELL THE BAR.
 * BI Reports' left nav can be pinned, which pads the content column by the nav's
 * width; the band is padded by the same amount so the capped, centred
 * .header-inner sits over the same box as the page under it. The app sets the
 * property (on body, when pinned) and never names this class — Audit-Header.
 * Unset, it is 0 and the bar is what every other tool draws. */
.app-header {
    width: 100%;
    height: var(--app-bar-h);
    padding: 0 0 0 var(--app-bar-inset-start, 0);
    box-sizing: border-box;
    background-color: var(--color-shell-bg);
    color: var(--color-shell-fg);
}

/* box-sizing: border-box, AND IT IS THE WHOLE SCROLLBAR BUG.
 *
 * height is --app-footer-h and there is a 1px border-top. In content-box — and
 * there is no global border-box reset in these sheets — the footer measures
 * --app-footer-h PLUS 1px. Statements sizes its page as
 * calc(100vh - --app-bar-h - --app-footer-h), so bar + page + footer came to
 * 100vh + 1px and the document carried a scrollbar at every window size, which
 * is exactly how it was reported. Measured: bar 57 + page 671 + footer 41 = 769
 * against a 768 viewport.
 *
 * The border belongs inside the token. Every tool that does this arithmetic —
 * and the bar already sets border-box on itself — gets it right now. */
.app-footer {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: var(--app-footer-h);
    padding: 0 var(--space-6);
    font-size: 0.75rem;
    color: var(--color-text-muted);
    background-color: var(--color-page-bg);
    border-top: 1px solid var(--color-border);
    flex-shrink: 0;
}

.app-footer p { margin: 0; padding: 0; }

/* THE CONTENT COLUMN. Horizontal padding matches .header-inner, so the tab strip
   and every page heading line up with the logo in the bar above.
   The COLUMN is centred, not the content: everything inside still starts at the
   column's own left edge, so a heading, a table and a filter panel share one
   left rule. Uncapped, a two-column filter panel on a 2560px monitor put
   "Select all / Clear" most of a metre from the "Branches" it belongs to;
   capping it and leaving it hard left then dropped the column into the left
   third and left a void beside it. */
/* THE BAND THAT SCROLLS.
 *
 * .page-shell is height:100vh with overflow:hidden, and between it and the
 * page the three Blazor tools render <div class="main-layout">, which had no
 * rule anywhere — not in the shared files, not in any app.css. So it was a
 * plain flex item that grew past the shell and was CLIPPED, with nothing able
 * to scroll: not the div, not <main>, not the document. Warranty Settings with
 * its sections expanded is about 2600px inside a 1390px shell, and everything
 * below the fold was unreachable.
 *
 * The scroll goes on the full-width band rather than on .main-content-area so
 * the scrollbar sits at the window edge, not inside the centred column. */
.page-shell > .main-layout {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.main-content-area {
    flex: 1;
    min-height: 0;
    padding: 20px 2em;
    max-width: var(--content-max-w);
    margin-left: auto;
    margin-right: auto;
}


/* --- THE TENANT PICKER ---------------------------------------------------------
 * Four apps defined this, each with its own hand-written copy of the shell field
 * tints — rgba(255,255,255,0.1 / 0.2 / 0.3 / 0.5 / 0.15). They happened to hold
 * the same values the tokens did, which is why nobody noticed, until
 * --color-shell-field-border moved 0.30 -> 0.35 for contrast and every bar
 * control followed except this one. A hand-copied token is not a token; it is a
 * value that agrees for now.
 *
 * Both shapes are here: the native <select> that some tools still render, and
 * the <fluent-select> the enhancer draws, which paints on ::part(control)
 * because its box is inside a shadow root. */
.company-dropdown {
    /* The control is dark because it sits in the bar; its POPUP is a list on the
       page and must not inherit that. Chrome builds the popup from the control's
       colour-scheme, so it is pinned light. */
    color-scheme: light;
    min-width: 200px;
    padding: var(--control-pad-y) var(--control-pad-x-tight);
    font-size: var(--font-size-control);
    border: 1px solid var(--color-shell-field-border);
    border-radius: var(--radius);
    background: var(--color-shell-control-bg);
    color: var(--color-shell-fg);
    cursor: pointer;
}

.company-dropdown:hover { background: var(--color-shell-control-bg-hover); }

.company-dropdown:disabled { cursor: not-allowed; }

/* The closed control sits in the dark bar, but the OPEN list is a popup drawn on
   the page: it takes the page surface and the page ink, like any other list. */
.company-dropdown option {
    background: var(--color-surface);
    color: var(--color-text);
}

/* THE PICKER IS A FILLED CONTROL, and it is the one thing in the bar that is.
 *
 * Midnight (--color-action-ink) on the bar's #1f2937, steel blue on hover and
 * while open. That is deliberate and it was chosen by eye: the tenant is the
 * single most consequential thing in the bar — every figure on the screen is
 * scoped by it — so it is the one affordance that reads as a control at rest
 * rather than waiting for the pointer. The link, the tabs and the caret beside
 * it stay flat.
 *
 * It was made flat for one round, on the reading that a lighter panel on a dark
 * bar was the "outline" being complained about. It was not; the complaint was
 * that the three Blazor tools still had this treatment and the React ones had
 * lost it. Same fill everywhere is the fix, not no fill.
 *
 * KEYED ON WHERE IT SITS, NOT ON A CLASS. This was
 * `fluent-select.company-dropdown`, and the three Blazor tools render
 * <FluentSelect> from the CompanySwitcher component with no Class at all — so
 * the flat treatment reached the three React tools and the Blazor ones kept the
 * filled box. The picker is the select inside .company-selector in every tool;
 * that is what identifies it, and it does not depend on anybody remembering to
 * add a class. */
/* One width, on the HOST, so the control is the same size before its contents
   are known — a picker that sizes to the tenant name is a different width in
   every tenant as well as in every tool. */
.company-selector fluent-select,
fluent-select.company-dropdown {
    /* All three, because Fluent gives its select a min-width of 250px of its own
       and a bare width loses to it — which is why the picker measured 230px in
       the React tools and 250px in the Blazor ones even after the width was
       shared. flex-basis too: the picker sits in a flex row in every tool and a
       flex item with width set can still be stretched by its container. */
    width: var(--tenant-w);
    min-width: var(--tenant-w);
    max-width: var(--tenant-w);
    flex: 0 0 var(--tenant-w);
}

.company-selector fluent-select::part(control),
fluent-select.company-dropdown::part(control) {
    padding: var(--control-pad-y) var(--control-pad-x-tight);
    font-size: var(--font-size-control);
    border: 1px solid var(--color-action-ink);
    border-radius: var(--radius);
    background: var(--color-action-ink);
    color: var(--color-action-hover-fg);
    cursor: pointer;
}

.company-selector fluent-select:hover::part(control),
fluent-select.company-dropdown:hover::part(control) {
    background: var(--color-action-hover);
    border-color: var(--color-action-hover);
}

/* OPEN IS LATCHED, and latched is the platform's steel blue — the same state
   My Views and the user menu show while their panel is down. The picker was the
   one bar control that opened a panel and did NOT change while it was open, so
   with the list hanging below it, it was the only trigger still looking at rest.
   It is a fluent-select, not a fluent-button, so the bar's latched rule never
   reached it; FAST sets aria-expanded and `open` on the host when it opens. */
.company-selector fluent-select[aria-expanded='true']::part(control),
.company-selector fluent-select[open]::part(control),
fluent-select.company-dropdown[aria-expanded='true']::part(control),
fluent-select.company-dropdown[open]::part(control) {
    background: var(--color-action-hover);
    border-color: var(--color-action-hover);
    color: var(--color-action-hover-fg);
    font-weight: 600;
}

fluent-select.company-dropdown[disabled]::part(control) { cursor: not-allowed; }

/* The tenant name, where a tool prints it as text rather than in the picker. */
.company-name { font-size: 0.9rem; }

/* The wordmark beside the logo. Four tools spelled this out; the size and weight
   were identical in all four, which is exactly why it should be said once. */
.header-brand h1 {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 500;
    color: var(--color-shell-fg);
}
