/* ============================================================================
   HAMROBILL APPLICATION SHELL
   ----------------------------------------------------------------------------
   The header row, the menu bar underneath it, and the panels that hang off
   both: the menus themselves, notifications, the profile menu and staff chat.

   THE MENU IS A BAR ACROSS THE TOP, and the rule this file exists to keep is
   that nothing in it is ever hidden, clipped or shortened.

   It was a column down the left-hand side for a while, because the bar it
   replaced kept running out of room: the menus shared one row with the logo,
   the search box and the profile control, so they were left with whatever was
   not already taken, and with nine of them the last ones were pushed off the
   edge and their names were ellipsized to "Default Setup Ca...". A ladder of
   breakpoints gave something else up at every width to try to keep up.

   None of that was about the bar being horizontal. It was about the bar being
   given the leftovers of a row. So the menu now has a row of its own, the full
   width of the window, and four rules keep it honest:

     * no ellipsis anywhere in it - not on a menu, not on a link in a panel;
     * the row WRAPS rather than overflowing, so menu number twenty starts a
       second line instead of disappearing;
     * a panel is as wide as its longest name needs and scrolls if it runs out
       of window, rather than squeezing a column until the names clip;
     * the shell measures itself and publishes the real height as
       --app-header-h, so the sticky toolbars and table headers on every page
       still clear the chrome when the row does wrap.

   No colour values live here. Everything resolves to the tokens in theme.css,
   which come from the brand palette in auth-theme.css - so the menu is the
   same colour as the rest of the application by construction, rather than by
   somebody remembering to update two files.
   ============================================================================ */

/* ─── THE SHELL ───

   One column, with the chrome stacked at the top of it. The header row and the
   menu row sit in one sticky block so they travel together.

   Nothing here is a scrolling box. Giving the content its own scroller would
   have been tidier on paper and would have broken every sticky report toolbar
   and table header in the product at once, because all of them are offset from
   the top of the VIEWPORT by --app-header-h. */
.app-shell {
    min-height: 100vh;
}

/* One block, one shadow. The two rows inside it are separated by a hairline
   rather than by each carrying its own shadow - two stacked shadows read as
   two floating bars rather than one piece of chrome. */
.app-top {
    position: sticky;
    top: 0;
    z-index: var(--z-nav, 1000);
    background: var(--c-surface, #fff);
    box-shadow: 0 1px 3px color-mix(in srgb, var(--auth-shade) 7%, transparent),
                0 8px 24px -12px color-mix(in srgb, var(--auth-shade) 16%, transparent);
}

.app-body {
    min-width: 0;
}


/* ─── THE HEADER ROW ───

   Brand, where you are, and the session controls. A fixed set of things: it
   cannot grow when a restaurant adds a menu, because the menus are not in it. */
.app-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: var(--app-bar-h, 52px);
    padding: 0 18px;
    background: var(--c-surface, #fff);
}

.app-header__lead {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    flex: 1 1 auto;
}

/* Opens the menu drawer on a phone or tablet, where the bar below is folded
   away. Hidden on the desktop, where the menu is always on screen. */
.app-header__burger {
    display: none;
    background: none;
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    width: 32px;
    height: 32px;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--c-ink-2);
    font-size: var(--fs-md);
    flex: 0 0 auto;
}

.app-header__burger:hover {
    background: var(--c-primary-soft);
    border-color: var(--c-primary);
    color: var(--c-primary);
}

/* ─── Brand ───

   Its mark sits at the same left edge as the first menu below it, and the two
   rows are read as one block because of it. Keep the paddings in step if
   either changes. */
.app-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
    text-decoration: none;
    color: var(--c-primary);
    font-size: var(--fs-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.app-brand:hover {
    color: var(--c-primary);
    background: transparent;
    text-decoration: none;
}

.app-brand:hover .app-brand__mark {
    box-shadow: 0 2px 8px var(--auth-primary-shadow);
}

.app-brand__mark {
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: var(--c-primary);
    color: var(--c-on-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-md);
    flex: 0 0 auto;
    transition: box-shadow var(--transition);
}

/* Where you are.

   The menu below already marks the section you are in; this says it in words,
   with the screen's own name, which a highlighted menu cannot. Read from the
   same menu tree the bar draws, so the two cannot disagree.

   Set off by a rule rather than sitting loose beside the brand - without it
   the screen's name reads as part of the product's name.

   This is the ONE thing in the chrome allowed to shorten itself: it repeats
   what the menu shows, so losing the tail of it costs nothing, whereas a menu
   name is the only place that screen is named. */
.app-header__where {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
    padding-left: 16px;
    margin-left: 4px;
    border-left: 1px solid var(--c-line-soft);
}

.app-header__section {
    font-size: var(--fs-sm);
    color: var(--c-ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 30ch;
}

.app-header__sep {
    font-size: 9px;
    color: var(--c-ink-4);
    flex: 0 0 auto;
}

.app-header__title {
    font-size: var(--fs-md);
    font-weight: var(--fw-semibold);
    color: var(--c-ink);
    letter-spacing: -0.005em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}


/* ═══════════════════════════════════════════════════
   THE MENU BAR
   ───────────────────────────────────────────────────
   Its own row, the full width of the window.

   The list is a flex row that WRAPS. That one declaration is what replaces the
   whole apparatus the old bar needed - overflow hiding, ellipsis on every
   name, panels sized from their column count, a breakpoint ladder - because a
   row that is allowed to wrap can never run out of room. Twenty menus cost two
   lines; nothing is dropped and no name is shortened.

   THE STATES. A menu is in one of four, and each one is a different KIND of
   thing, so each is drawn differently rather than by turning one effect up:

     rest      ink on the bar, nothing else
     hover     a soft tinted pill - "this is what you would click"
     open      the same pill with its caret turned - "this panel belongs here"
     current   the same soft pill, bold text, and a thin underline - "this is
               where you are"

   The current menu used to be a FILLED pill - solid maroon, white text. That
   read as too strong and too colourful for something sitting in the bar on
   every single screen: it fought with the brand mark, and next to nine other
   menus in their quiet ink colour it was the loudest thing on the page for no
   reason tied to what the user was doing. It is now the same soft tint hover
   already uses - so a click always lands where the colour said it would - set
   apart from a plain hover only by bold text and a slim underline, which is
   enough to find at a glance without shouting.
   ═══════════════════════════════════════════════════ */
/* The padding is the header's own (18px) MINUS a pill's internal padding
   (12px), so the first menu's icon lands on the same vertical line as the
   brand mark above it rather than 12px inside it. The two must move together:
   if either padding changes, this one does too. */
.tnav {
    background: var(--c-surface);
    border-top: 1px solid var(--c-line-soft);
    border-bottom: 1px solid var(--c-line);
    padding: 0 6px;
}

.tnav__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    /* Column gap is small because each pill already carries its own padding;
       the row gap is what keeps a wrapped second line from crowding the first. */
    gap: 2px 3px;
}

/* Full height of the bar, so a panel hung at top:100% lands on the bar's
   bottom edge rather than part-way up it. The pill inside is inset. */
.tnav__row {
    position: relative;
    display: flex;
    align-items: center;
    /* The bar has no height of its own - it is as tall as this row makes it,
       and --app-menu-h in theme.css only states what that comes to. Keep the
       two in step: 34px pill + 4px above + 4px below + the two hairlines on
       .tnav = 44px. */
    padding: 4px 0;
}

.tnav__empty {
    display: flex;
    align-items: center;
    height: 34px;
    padding: 0 8px;
    font-size: var(--fs-sm);
    color: var(--c-ink-4);
}

/* ─── A menu in the bar ───

   NEVER truncated. No overflow, no text-overflow, no max-width: the name is
   the only place that screen is named in the chrome, so if it is long the bar
   gives it the room and wraps the row instead. */
.tnav__item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    padding: 0 12px;
    border: 0;
    border-radius: var(--r-lg);
    background: transparent;
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    line-height: 1.2;
    letter-spacing: -0.005em;
    color: var(--c-ink-2);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--transition), color var(--transition),
                box-shadow var(--transition);
}

/* Hover, and the menu whose panel is showing. The same tint for both on
   purpose: a panel opens on hover, so they are the same gesture, and giving
   them two different colours made the bar flicker between them.

   The text-decoration is not redundant: theme.css underlines every `a:hover`
   in the product, which is right for a link in a sentence and wrong inside a
   pill - the underline landed under the name and made the row look broken. */
.tnav__item:hover,
.tnav__section.is-open > .tnav__item {
    background: var(--c-primary-soft);
    color: var(--c-primary);
    text-decoration: none;
}

/* Keyboard focus is its own mark, outside the pill, so it is still visible on
   the filled current menu where a background change would not be. */
.tnav__item:focus-visible,
.tnav__link:focus-visible {
    outline: 2px solid var(--c-primary);
    outline-offset: 2px;
}

/* Where you are: the screen itself, or the menu holding it. The same soft
   tint as hover - so hover never has to lie about what a click would do -
   set apart by weight and a thin underline rather than by turning the colour
   up, which is what made this read as too strong. */
.tnav__item.is-active,
.tnav__section.is-current > .tnav__item {
    background: var(--c-primary-soft);
    color: var(--c-primary);
    font-weight: var(--fw-semibold);
    box-shadow: inset 0 -2px 0 0 var(--c-primary);
}

.tnav__item.is-active:hover,
.tnav__section.is-current > .tnav__item:hover,
.tnav__section.is-current.is-open > .tnav__item {
    background: color-mix(in srgb, var(--c-primary-soft) 78%, var(--c-primary) 22%);
    color: var(--c-primary);
}

.tnav__icon {
    font-size: 13px;
    width: 15px;
    text-align: center;
    flex: 0 0 auto;
    color: var(--c-ink-4);
    transition: color var(--transition);
}

/* The icon follows the pill it is in rather than keeping its own colour -
   two colours inside one filled pill reads as a mistake. */
.tnav__item:hover .tnav__icon,
.tnav__item.is-active .tnav__icon,
.tnav__section.is-current > .tnav__item .tnav__icon,
.tnav__section.is-open > .tnav__item .tnav__icon {
    color: inherit;
}

.tnav__caret {
    font-size: 9px;
    margin-left: -2px;
    opacity: 0.55;
    flex: 0 0 auto;
    transition: transform var(--transition), opacity var(--transition);
}

.tnav__item:hover .tnav__caret {
    opacity: 0.9;
}

.tnav__section.is-open > .tnav__item .tnav__caret {
    transform: rotate(180deg);
    opacity: 1;
}


/* ─── A menu's panel ───

   One shape for all of them. The bar used to draw three - "mega", "dropdown"
   and "grouped" - and all three existed to fit different numbers of links into
   a horizontal panel without it running off the screen. There is one here: a
   grid of groups, as many columns wide as the window has room for.

   IT IS NEVER WIDER THAN THE WINDOW, and never wider than its own sections
   need either. Those are two different rules and the panel needs both.

   The first is what a panel anchored to its menu could not promise: it was
   only as wide as the space left beside that menu, so a menu with a lot of
   links had to either squeeze its columns until the names clipped or let the
   panel scroll SIDEWAYS - and a link you have to go looking for with a
   horizontal scrollbar is as good as hidden. The window is the ceiling now,
   and the sections reflow into however many columns fit under it.

   The second is what stops that ceiling from becoming the floor as well. A
   panel pinned to both edges is a strip across the whole screen whatever is
   in it, so a menu with two short sections opened a 1300px band with 1000px
   of nothing in it. --tnav-cols is how many sections this menu actually has
   (TopNav.razor), so the panel asks for room for that many and no more; only
   a menu with enough sections to fill the window reaches the edges.

   Fixed to the viewport rather than to the row, because the row it belongs to
   may be the second line of a wrapped bar and only the viewport knows where
   the chrome ends. --app-header-h is the measured height of that chrome (see
   measureChrome in menu.js), so the panel sits flush against the bar's bottom
   edge whether the bar is one line or two - and flush matters: the panel opens
   on hover, and a gap is a strip of dead page the pointer has to cross, which
   shuts the thing it was reaching for.

   HORIZONTALLY it is centred on the menu that opened it, which is placeMenuPanel
   in menu.js writing an inline left onto this element after the render that
   opened it - a fixed element cannot be centred on another one in CSS alone,
   because CSS cannot see where in the viewport the menu landed. The left below
   is only what the panel opens at for the one frame before that lands, and the
   clamp that keeps it on screen lives there too. Anchoring matters: at left: 0
   the panel for the LAST menu in the bar appeared at the far left of the
   window, with nothing tying it to the name under the pointer. */
.tnav__sub {
    display: none;
    position: fixed;
    top: var(--app-header-h, 88px);
    left: 8px;
    width: min(calc(100vw - 16px), calc(var(--tnav-cols, 3) * 250px + 34px));
    z-index: var(--z-nav-menu, 1100);
    /* Height is the one axis a panel may still run out of, and the one where
       scrolling costs nothing: everything is in the column you are already
       reading down. */
    max-height: calc(100vh - var(--app-header-h, 88px) - 16px);
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* The bottom is 0 on purpose and not a missing value: the card that ends a
       column brings its own 14px bottom margin with it, and a padding under
       that would land the panel's bottom edge 14px further from the last card
       than its top edge is from the first. The two gaps are equal as written -
       14px of padding above, 14px of margin below - which is what stops the
       panel from looking bottom-heavy. If the card margin changes, this
       changes with it. */
    padding: 14px 16px 0;
    background: var(--c-surface, #fff);
    /* It has a right-hand edge now that it is not pinned to both sides, so it
       needs to look like one: a border and a corner where the panel stops,
       and a shadow deep enough to read as a surface over the page rather than
       as part of it. */
    border-left: 1px solid var(--c-line);
    border-right: 1px solid var(--c-line);
    border-bottom: 1px solid var(--c-line);
    border-radius: 0 0 var(--r-lg, 10px) var(--r-lg, 10px);
    box-shadow: 0 18px 40px -12px color-mix(in srgb, var(--auth-shade) 26%, transparent);
}

.tnav__section.is-open > .tnav__sub {
    display: block;
    animation: tnavPanelIn 130ms cubic-bezier(0.2, 0, 0.2, 1);
}

@keyframes tnavPanelIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Sections FLOW down one column and on into the next. They used to be cells in
   a row grid, and a row grid gives every cell in a row the height of the
   tallest one in it - so a four-link section sitting beside a thirteen-link
   one got a four-link card and nine links' worth of blank space underneath,
   and the next section could not start until the whole row had ended. On a
   real menu that was most of the panel: a third of its height was holes.

   Flowing columns have no rows to line up, so a short section is followed
   immediately by the next one and the panel is only as tall as its contents.

   `columns: <width> <count>` is a maximum of --tnav-cols columns, each at
   least 230px wide: the count is what the menu asked for, and the width is
   what stops a narrow window from honouring it by slicing the panel into
   strips too thin to read. Whichever binds first wins, so this never needs a
   breakpoint.

   230px is a measured floor, not a round number: a column has to hold a name
   and its shortcut side by side ("Stock Control" and Ctrl+Alt+K) once the card
   and the row have taken their padding - 36px of it between them, down from 42
   now that the list inside the card has no padding of its own. Below this the
   names start wrapping onto second lines, which is legible but ragged. */
.tnav__grid {
    display: flex;
    align-items: flex-start;
    gap: 20px;
}

/* One column, packed in C# (see ColumnsOf in TopNav.razor) rather than by the
   CSS multi-column balancer.

   The balancer was the obvious tool and could not do the job: every section
   carries break-inside:avoid, so a fourteen-row section is indivisible, and
   with one of those beside several four-row ones it had nothing left to
   balance - two columns filled and two stopped a third of the way down.

   flex-basis 0 with flex-grow 1 makes the columns equal in WIDTH regardless
   of what is in them, which is what keeps the panel looking like a grid; the
   230px floor is the same measured minimum the multi-column rule used, below
   which a name and its shortcut stop fitting side by side. */
.tnav__col {
    flex: 1 1 0;
    min-width: 0;
    max-width: 320px;
}

/* Each section is a card, because in a flowing column the sections sit
   directly on top of one another and a hairline under a small caps label is
   not enough to say where one ends and the next begins - "COMPANY" over four
   links over "PEOPLE" over six read as one long list with two labels in it.

   ONE BORDER, NO FILL. The card used to be a tinted box with a white list
   inset inside it, which is three surfaces deep once the panel underneath is
   counted - and because the list covered the middle of the card, the tint only
   ever showed as a strip behind the heading and a thin halo around the links.
   It read as something not quite painting correctly rather than as a card.

   A boundary needs one mark, not a mark and a wash. So the fill is gone from
   both this and the list inside it, everything sits on the panel's own
   surface, and the card is a hairline and a corner - the same hairline the
   panel itself is drawn with, because it is the same kind of edge. --c-line
   rather than the softer one it used to carry: with nothing behind it the
   border is the whole of the boundary now, so it has to be visible on its own.

   break-inside keeps a section whole - a card cut in half by a column break,
   its links continuing under no heading at all, is worse than an uneven
   column. */
/* ONE SUBMENU DESIGN, EVERYWHERE.

   Settings, User and the loose links in any menu were drawn without a box -
   there is no named section to put a boundary around - while Setup, Payment
   and Report drew every section as a bordered card. Same component, same kind
   of content, two different-looking menus, and the boxed one was the odd one
   out: a card around every section made the Setup panel read as six separate
   widgets and cost 20px of height apiece, which is most of why that one menu
   scrolled on a laptop while the others fitted.

   The boundary a named section needs is already there without the box: a
   quiet uppercase label with a hairline under it, over full-strength links.
   That is what Settings looks like, and it is now what all of them look like.
   The only difference left between a titled section and an untitled slice is
   the title itself - which IS the functional difference, and the only one. */
.tnav__group {
    break-inside: avoid;
    /* The gap between one section and the next, and - see .tnav__sub - the gap
       under the last one as well. Sections are told apart by their heading
       now rather than by a box, so they need a little more air between them
       than two cards did. */
    margin: 0 0 18px;
    /* No side inset of its own any more: the heading and every link carry
       their own 10px, so their text still lines up and the heading's rule
       runs the full width of the column. */
    padding: 0;
    background: none;
    border: none;
}

/* Kept as a hook - a slice of a flat menu has no heading, so it also has no
   rule above its links and needs no space for one. */
.tnav__group--plain {
    border: none;
}

/* The heading and the links under it are two different tiers, and they used to
   be drawn as if they were one: the heading was small brand-coloured caps and
   the links were brand-tinted ink, so the panel came out all one hue and the
   heading read as just another row in a slightly smaller size.

   They are told apart by KIND now, not by size. The heading is a quiet grey
   label - the name of the box you are looking in - and the links inside it are
   full-strength ink, which is the thing you actually came to read. Only the
   icon keeps the brand colour, so each section still has one point of colour
   to find it by.

   Its text is indented by the same 10px a link's is, so the heading and the
   choices under it share a left edge - they used to start 8px apart, which is
   near enough to look like a mistake and far enough to see. The indent is
   padding rather than margin so the rule underneath still spans the card from
   border to border instead of stopping short of both.

   11px rather than 10px: it is a label above a list of 14px names, and at 10px
   uppercase with letters spaced apart it had stopped being comfortably
   readable to say something that small. */
.tnav__group-title {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 8px;
    padding: 0 10px 9px;
    border-bottom: 1px solid var(--c-line-soft);
    font-size: 11px;
    font-weight: var(--fw-bold, 700);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--c-ink-3, #8a7f75);
    overflow-wrap: break-word;
}

.tnav__group-title i {
    font-size: 11px;
    color: var(--c-primary);
    flex: 0 0 auto;
}

/* No surface of its own. This was a white panel inset inside the tinted card,
   there to hold the links apart from the heading above them - but the heading
   is a quiet grey label and the links are full-strength ink at a larger size,
   which tells them apart on its own, and the rule under the heading says where
   one ends and the other starts. A second box to make the same point cost a
   third surface and 3px off every column's width. */
.tnav__group-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Rows used to sit flush against each other with nothing but a link's own
   padding between them, which is what made a nine-row column look like one
   crowded block instead of nine separate choices. A small gap between rows
   is enough to read them as a list. Margin rather than a flex gap: this list
   also has to keep working as a CSS multi-column flow in a wide group, which
   flex does not support. */
.tnav__group-list > li + li {
    margin-top: 2px;
}

/* ─── A link in a panel ───

   Also never truncated. The column has a width now - the window decides how
   many columns there are, so a column cannot simply grow to fit its longest
   name the way it did when the panel scrolled sideways - so a name longer than
   its column takes a second LINE instead. Wrapping costs a few pixels of
   height; the alternatives are hiding letters behind an ellipsis or making the
   reader scroll sideways to find out what a menu item is called, and neither
   is allowed to happen. */
.tnav__link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 9px;
    min-height: 30px;
    /* 10px of side padding, matching the heading's, so the two line up; the
       card's own 8px is what keeps the hover shape off the border. */
    padding: 5px 10px;
    border-radius: 7px;
    font-size: var(--fs-base);
    /* Plain body ink. These used to carry a wash of the brand colour, which
       was there to hold them apart from the heading above - but the heading
       was brand-coloured too, so the wash made the whole panel one hue and
       separated nothing. The heading is grey now and these are ink, which is
       the same distinction made with more contrast and less colour. */
    font-weight: var(--fw-medium, 500);
    color: var(--c-ink-2);
    text-decoration: none;
    /* break-word, NOT anywhere. `anywhere` also shrinks the element's
       min-content width to one character, which tells the column it can be as
       narrow as it likes - so "Stock Control" came out broken across two lines
       as "Stock Contro / l" while there was still room to wrap at the space.
       break-word wraps between words first and only splits a word that cannot
       fit on a line of its own. */
    overflow-wrap: break-word;
    /* If the name, the flag and the shortcut genuinely cannot share a line,
       the shortcut drops to the next one. Nothing is hidden and no word is
       split - the row just gets taller, which is the cheap end of the
       never-truncate rule this file is built on. */
    flex-wrap: wrap;
    transition: background var(--transition), color var(--transition);
}

.tnav__link:hover {
    background: var(--c-primary-soft);
    color: var(--c-primary);
    text-decoration: none;
}

/* The screen you are on. The same tint as hover would make the two
   indistinguishable the moment the pointer landed on it, so this one carries a
   bar down its leading edge and the heavier weight as well. */
.tnav__link.is-active {
    background: var(--c-primary-soft);
    color: var(--c-primary);
    font-weight: var(--fw-semibold);
}

/* Inset past the row's 7px corner at both ends, so the bar is square against
   the straight part of the highlight instead of overhanging where it curves. */
.tnav__link.is-active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 7px;
    bottom: 7px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--c-primary);
}


/* ═══════════════════════════════════════════════════
   THE DRAWER  (phone and tablet)
   ───────────────────────────────────────────────────
   There is no room for a row of menus on a phone, so below 992px the bar folds
   behind the header's button and opens as a full-height panel. Every menu is
   still in it, with its full name - it is a different arrangement of the same
   list, not a shorter one.
   ═══════════════════════════════════════════════════ */
.nav-scrim {
    display: none;
    position: fixed;
    inset: 0;
    background: color-mix(in srgb, var(--auth-shade) 42%, transparent);
    z-index: calc(var(--z-nav-menu, 1100) - 1);
}

/* ─── HEADER ACTIONS (RIGHT) ─── */
.header-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

.action-btn {
    position: relative;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--c-surface-2);
    border: 1px solid transparent;
    border-radius: 7px;
    cursor: pointer;
    font-size: var(--fs-base);
    color: var(--c-primary);
    transition: all 0.2s ease;
}

.action-btn:hover {
    background: var(--c-primary);
    color: #fff;
}

.action-badge {
    position: absolute;
    top: -3px;
    right: -3px;
    background: var(--c-danger);
    color: #fff;
    font-size: var(--fs-xs);
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 8px;
    min-width: 16px;
    text-align: center;
    line-height: 1.4;
}

.action-btn-wrapper {
    position: relative;
}

.header-divider {
    width: 1px;
    height: 22px;
    background: var(--c-line);
    margin: 0 4px;
}



/* ─── ACTION DROPDOWNS (Notifications) ─── */
.action-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 320px;
    background: #fff;
    border-radius: 12px;
    box-shadow: var(--sh-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: all 0.25s ease;
    z-index: 1100;
    overflow: hidden;
}

.action-dropdown.active {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.dropdown-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--c-line-soft);
}

.dropdown-header h4 {
    margin: 0;
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--c-ink);
}

.dropdown-badge {
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--c-primary);
    background: var(--c-primary-soft);
    padding: 2px 8px;
    border-radius: 10px;
}

.dropdown-body {
    max-height: 280px;
    overflow-y: auto;
    padding: 4px;
}

.dropdown-item-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.15s;
}

.dropdown-item-row:hover {
    background: var(--c-surface-2);
}

.notif-icon-circle {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--c-primary-soft);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--c-primary);
    font-size: var(--fs-base);
    flex-shrink: 0;
}

.notif-text {
    font-size: var(--fs-base);
    color: var(--c-ink);
    line-height: 1.4;
}

.dropdown-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 24px 16px;
    color: var(--c-ink-4);
    gap: 6px;
}

.dropdown-empty i {
    font-size: var(--fs-2xl);
}

.dropdown-empty span {
    font-size: var(--fs-base);
}

.dropdown-footer {
    padding: 10px 16px;
    border-top: 1px solid var(--c-line-soft);
    text-align: center;
}

.dropdown-footer a {
    font-size: var(--fs-base);
    color: var(--c-primary);
    text-decoration: none;
    font-weight: 500;
    transition: opacity 0.2s;
}

.dropdown-footer a:hover {
    opacity: 0.7;
}


/* ─── PROFILE ─── */
.profile-wrapper {
    position: relative;
}

.profile-trigger {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px 4px 4px;
    background: var(--c-surface-2);
    border-radius: 24px;
    cursor: pointer;
    transition: background 0.2s;
}

.profile-trigger:hover {
    background: var(--c-line-soft);
}

.profile-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid var(--c-primary);
    object-fit: cover;
}

.profile-info {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.profile-name {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--c-ink);
}

.profile-role {
    font-size: var(--fs-xs);
    color: var(--c-ink-3);
}

.profile-arrow {
    font-size: var(--fs-xs);
    color: var(--c-ink-3);
    transition: transform 0.2s;
}

.profile-wrapper:hover .profile-arrow {
    transform: rotate(180deg);
}

/* Profile Dropdown */
.profile-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 260px;
    background: var(--c-surface, #fff);
    border: 1px solid var(--c-line);
    border-radius: 12px;
    box-shadow: var(--sh-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: all 0.25s ease;
    /* Was a literal 1100. The one place stacking order is decided is
       theme.css section 1; an open header menu is --z-nav-menu. */
    z-index: var(--z-nav-menu, 1100);
    overflow: hidden;
}

.profile-dropdown.active {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.profile-dropdown-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    background: var(--c-primary-soft);
    border-bottom: 1px solid var(--c-line-soft);
}

.profile-dropdown-header img {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 2px solid var(--c-primary);
}

.profile-dropdown-name {
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--c-ink);
}

.profile-dropdown-email {
    font-size: var(--fs-xs);
    color: var(--c-ink-3);
}

.profile-dropdown-body {
    padding: 6px;
}

.profile-dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    color: var(--c-ink-2);
    text-decoration: none;
    font-size: var(--fs-base);
    border-radius: 6px;
    transition: all 0.15s;
}

.profile-dropdown-item:hover {
    background: var(--c-surface-2);
    color: var(--c-primary);
}

.profile-dropdown-item i {
    width: 16px;
    text-align: center;
    font-size: var(--fs-base);
    opacity: 0.6;
}

.profile-dropdown-item:hover i {
    opacity: 1;
}

.profile-dropdown-footer {
    padding: 4px 6px 6px;
    border-top: 1px solid var(--c-line-soft);
}

.logout-item {
    color: var(--c-danger) !important;
}

.logout-item:hover {
    background: var(--c-danger-soft) !important;
    color: var(--c-danger) !important;
}


/* ─── ANIMATIONS ─── */
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.action-dropdown.active,
.profile-dropdown.active {
    animation: fadeInUp 0.2s ease;
}


/* ─── SCROLLBAR ─── */
.dropdown-body::-webkit-scrollbar {
    width: 5px;
}

.dropdown-body::-webkit-scrollbar-track {
    background: var(--c-line-soft);
    border-radius: 10px;
}

.dropdown-body::-webkit-scrollbar-thumb {
    background: var(--c-primary);
    border-radius: 10px;
}


/* Dragging across a menu selects its text, which is never what was meant. */
.tnav,
.action-dropdown,
.profile-dropdown {
    user-select: none;
    -webkit-user-select: none;
}


/* ═══════════════════════════════════
   RESPONSIVE BREAKPOINTS
   ───────────────────────────────────
   Short, and deliberately so. The bar this replaced had a ladder of them -
   drop the menu icons at 1200, shrink the mega panel at 1400, force three
   columns, hide the profile name - because it was trying to fit the menus into
   a row it was sharing with everything else, and something had to be given up
   at every width.

   A row of its own that is allowed to wrap does not need any of that. What is
   left here changes the SHAPE of the chrome, never its contents: the header's
   own controls tighten up, the menu pills tighten before the row wraps, and on
   a phone the bar folds into a drawer. No menu and no menu name is dropped at
   any width.
   ═══════════════════════════════════ */

@media (max-width: 1400px) {
    /* The tenant name beside the avatar is the first thing worth losing:
       there is one account signed in and its name is inside the menu. */
    .profile-info {
        display: none;
    }
}

@media (max-width: 1280px) {
    .app-header {
        padding: 0 14px;
        gap: 12px;
    }

    /* 14px header padding - 11px pill padding; see the note on .tnav. */
    .tnav {
        padding: 0 3px;
    }

    /* Tighter pills, so more menus fit on a line before the row wraps. The
       padding gives way; the names never do. */
    .tnav__item {
        padding: 0 11px;
        gap: 7px;
    }

    /* Bottom stays 0 for the reason given on .tnav__sub: the last card's own
       margin is the gap under it. */
    .tnav__sub {
        padding: 12px 13px 0;
    }

    .tnav__grid {
        column-gap: 16px;
    }
}

@media (max-width: 1100px) {
    /* The trail repeats what the bar below already shows, so it is the right
       thing to drop when the header row gets tight - unlike the controls on
       the right, which are nowhere else. */
    .app-header__where {
        display: none;
    }
}


/* ─── DRAWER: phone and tablet ───

   Below 992px there is no room for a row of menus, so the bar folds behind the
   header's button and the same list is stacked in a panel. A different
   arrangement, not a shorter one: every menu is in it, with its full name, and
   a long name is allowed the second line that a row could not give it.
   ─────────────────────────────── */
@media (max-width: 992px) {
    .app-header {
        padding: 0 12px;
    }

    .app-header__burger {
        display: flex;
    }

    .app-brand__text {
        display: none;
    }

    .tnav {
        display: none;
        position: fixed;
        top: var(--app-bar-h, 52px);
        left: 0;
        bottom: 0;
        width: min(324px, 88vw);
        padding: 10px 10px 20px;
        overflow-y: auto;
        overscroll-behavior: contain;
        background: var(--c-surface, #fff);
        border-top: 0;
        border-right: 1px solid var(--c-line);
        border-bottom: 0;
        box-shadow: var(--sh-lg);
        z-index: var(--z-nav-menu, 1100);
    }

    html.nav-open .tnav {
        display: block;
    }

    html.nav-open .nav-scrim {
        display: block;
    }

    /* The page behind must not scroll while the drawer is over it. */
    html.nav-open body {
        overflow: hidden;
    }

    .tnav__list {
        flex-direction: column;
        flex-wrap: nowrap;
        align-items: stretch;
        gap: 2px;
    }

    .tnav__row {
        display: block;
        padding: 0;
    }

    .tnav__item {
        width: 100%;
        height: auto;
        min-height: 44px;
        padding: 10px 12px;
        border-radius: var(--r-lg);
        /* The one place a long name is allowed to use two lines: the drawer is
           a column, so height is free and nothing has to give. */
        white-space: normal;
    }

    .tnav__label {
        flex: 1 1 auto;
        min-width: 0;
        text-align: left;
    }

    /* The caret belongs at the far end of a full-width row, not tucked against
       the name as it is in the bar. */
    .tnav__caret {
        margin-left: auto;
    }

    /* Inline, under the menu it belongs to - there is no room beside it, and
       nothing to span the width of: the drawer IS the width. */
    .tnav__sub {
        position: static;
        width: auto;
        max-height: none;
        overflow: visible;
        padding: 2px 0 8px 10px;
        border: 0;
        border-left: 2px solid var(--c-primary-soft);
        border-radius: 0;
        margin: 2px 0 6px 18px;
        box-shadow: none;
        background: transparent;
        animation: none;
    }

    /* One column, however many the window would have fitted. */
    .tnav__grid {
        columns: auto 1;
    }

    /* The card comes off here. The drawer is already one narrow column inside
       a fixed panel - boxing each section inside that as well is two frames
       deep for a list of links, and the width they cost is width the names
       need. A rule above each section but the first separates them on its own.

       The heading keeps its 10px indent and so do the links, so they still
       share a left edge without the card that set it on the desktop. */
    .tnav__group {
        margin: 0;
        padding: 0;
        border: 0;
        border-radius: 0;
    }

    .tnav__group + .tnav__group {
        padding-top: 10px;
        margin-top: 8px;
        border-top: 1px solid var(--c-line-soft);
    }

    .tnav__group-title {
        margin-top: 0;
    }

    .tnav__link {
        padding: 9px 10px;
    }

    /* A phone has no keyboard to press them on, and the row needs its width
       for the name. */
    .tnav-key {
        display: none;
    }
}

@media (max-width: 640px) {
    /* Already gone at 1100px on a desktop window; this keeps it gone if a
       phone reports a wider layout viewport. */
    .app-header__section,
    .app-header__sep {
        display: none;
    }
}

/* ═══════════════════════════════════════════════════
   Profile avatar — initials
   ───────────────────────────────────────────────────
   Replaces the <img> that pointed at i.pravatar.cc. That was a stock photo of
   a stranger, identical for every user of every restaurant, fetched from a
   third party on every page load.
   ═══════════════════════════════════════════════════ */

.profile-avatar--initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border-radius: 50%;
    background: var(--c-primary);
    color: var(--c-on-primary);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    user-select: none;
}

/* The dropdown header's copy is slightly larger, as the <img> there was. */
.profile-dropdown-header .profile-avatar--initials {
    width: 44px;
    height: 44px;
    flex-basis: 44px;
    font-size: var(--fs-md);
}

/* The menu now holds a <button> beside its links, so it has to look like the
   links rather than like a button. */
button.profile-dropdown-item {
    width: 100%;
    background: none;
    border: 0;
    text-align: left;
    font: inherit;
    cursor: pointer;
    display: flex;
    align-items: center;
}

button.profile-dropdown-item .sc-key { margin-left: auto; }

/* ═══════════════════════════════════════════════════
   Menu names
   ───────────────────────────────────────────────────
   There used to be four hundred lines here, and all of them were about
   fitting names into a space that was too small: a mega panel sized from the
   number of columns it needed, long columns splitting in two so the panel grew
   sideways instead of running off the bottom of the window, flat panels
   flowing into two columns past eight rows, names ellipsizing in the bar and
   wrapping inside the panels, and a height cap under all of it in case the
   reflow still was not enough.

   The whole of it came from one decision - that the row had to hold every menu
   whatever its width - and it is not made any more. The row wraps, so the
   names need no help at all: this is the entire rule, and there is deliberately
   no `overflow: hidden` and no `text-overflow: ellipsis` anywhere near a menu
   name. Hiding letters ("Default Setup Ca...") in the one place a person reads
   the names is the wrong thing to give up.
   ═══════════════════════════════════════════════════ */
.tnav__label {
    /* Takes the free space before the badge and the shortcut chip do, and -
       the part that was missing - refuses to shrink below its longest word.

       It was `min-width: 0`, which let the two chips beside it hold their
       natural size while the name gave up everything: in a 163px column,
       "Stock Control" was squeezed into 38px, narrower than the word
       "Control", so overflow-wrap had no choice but to split it and the menu
       read "Stock Contr / ol". min-content stops the squeeze at the longest
       word, so the name wraps at the space instead - which is what the
       break-word comment above was trying to achieve. */
    flex: 1 1 auto;
    min-width: min-content;
    line-height: 1.3;
}

/* In a panel row the label's basis is 0, not its full width. With `auto`, a
   flex row that is allowed to wrap compares each item's WHOLE width before
   shrinking anything - so "Table Reservations NEW" plus Ctrl+Alt+T wrapped
   the key onto a line of its own even though the name could simply have
   wrapped its words. From 0 the label shrinks first (never below its longest
   word, per min-content above) and the key only drops as a last resort. */
.tnav__link > .tnav__label {
    flex-basis: 0%;
}


/* ═══════════════════════════════════════════════════
   Highlight flags
   ───────────────────────────────────────────────────
   "New" and "Tip" beside the few screens worth pointing at. The catalogue is
   MenuHighlights.cs and the rule there is that this stays short - the moment
   a third of the menu is flagged, a flag stops meaning anything.

   Deliberately quieter than the brand: a menu is for navigating, and a row of
   coloured chips competing with the names would make it harder to use, not
   easier. The flag is small and sits after the name.
   ═══════════════════════════════════════════════════ */

.tnav-flag {
    flex: 0 0 auto;
    /* Inline inside a panel row's label (see RenderLeaf), so it wraps with the
       name rather than claiming a column of its own. */
    display: inline-block;
    vertical-align: 1px;
    margin-left: 6px;
    padding: 0 5px;
    font-size: 9px;
    font-weight: 700;
    line-height: 15px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    border-radius: 3px;
    white-space: nowrap;
}

/* Shipped recently. */
.tnav-flag--new {
    color: #fff;
    background: var(--c-primary, #a8394a);
}

/* Been there a while and is worth a look. Outlined rather than filled, so the
   two read as different kinds of claim at a glance. */
.tnav-flag--tip {
    color: var(--c-ink-3, #8a7f75);
    background: transparent;
    border: 1px solid var(--c-line-strong, #d8cec2);
}

@media (max-width: 992px) {
    /* The drawer is narrow and the names matter more than the badges. */
    .tnav-flag { display: none; }
}


/* ═══════════════════════════════════════════════════
   STAFF CHAT
   ───────────────────────────────────────────────────
   A flyout on the header, sized and shaped like the notification dropdown
   beside it, because it is the same kind of object and should not need
   learning twice.

   Two panes in one panel: the staff list, and one conversation. They swap
   rather than sitting side by side - at 340px there is only room for one,
   and a till screen has no space to spare for a permanent sidebar.
   ═══════════════════════════════════════════════════ */

.chat-wrapper { position: relative; }

/* Closes the panel when you click away. Invisible, but it does have to be
   there: the header's JS click-outside handler only knows about the
   dropdowns whose visibility it owns, and this one is Blazor's. */
.chat-backdrop {
    position: fixed;
    inset: 0;
    background: transparent;
    z-index: 1090;
}

.chat-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 340px;
    max-width: calc(100vw - 24px);
    height: 460px;
    max-height: calc(100vh - var(--app-header-h, 88px) - 24px);
    display: flex;
    flex-direction: column;
    background: #fff;
    border-radius: 12px;
    box-shadow: var(--sh-lg);
    z-index: 1100;
    overflow: hidden;
}

.chat-panel__head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--c-line-soft);
    flex: 0 0 auto;
}

.chat-panel__head h4 {
    margin: 0;
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--c-ink);
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chat-online-count,
.chat-role {
    margin-left: auto;
    font-size: var(--fs-xs);
    color: var(--c-ink-3);
    white-space: nowrap;
}

.chat-back {
    background: none;
    border: 0;
    padding: 2px 4px;
    cursor: pointer;
    color: var(--c-ink-3);
    font-size: var(--fs-base);
}

.chat-back:hover { color: var(--c-primary); }

.chat-panel__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    padding: 6px;
}

/* ─── Staff list ─── */

.chat-contact {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    background: none;
    border: 0;
    border-radius: 8px;
    text-align: left;
    cursor: pointer;
    font: inherit;
    transition: background 0.15s;
}

.chat-contact:hover { background: var(--c-surface-2); }

.chat-avatar {
    position: relative;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--c-primary-soft);
    color: var(--c-primary);
    font-size: var(--fs-sm);
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The presence light. Green only ever means "connected right now" - it is
   read from the hub's live socket list, never from a stored flag, because a
   stored flag drifts to "everyone is here" the first time a browser closes
   without signing out. */
.chat-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--c-ink-4, #a39689);
    border: 2px solid #fff;
    flex: 0 0 auto;
}

.chat-avatar .chat-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
}

.chat-dot.is-online { background: var(--c-success, #916723); }

.chat-contact__text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.chat-contact__top {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

.chat-contact__name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--fs-base);
    color: var(--c-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chat-contact__when {
    flex: 0 0 auto;
    font-size: 10px;
    color: var(--c-ink-4);
}

.chat-contact__sub {
    font-size: var(--fs-xs);
    color: var(--c-ink-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chat-unread {
    flex: 0 0 auto;
    min-width: 18px;
    padding: 0 5px;
    font-size: 10px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    color: #fff;
    background: var(--c-primary);
    border-radius: 9px;
}

/* ─── Conversation ─── */

.chat-thread {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    background: var(--c-surface-2);
}

.chat-msg {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    max-width: 82%;
}

.chat-msg--mine {
    align-self: flex-end;
    align-items: flex-end;
}

.chat-bubble {
    padding: 7px 11px;
    border-radius: 12px 12px 12px 3px;
    background: #fff;
    border: 1px solid var(--c-line-soft);
    font-size: var(--fs-sm);
    color: var(--c-ink);
    line-height: 1.45;
    /* A pasted order or a long sentence has to wrap, and an unbroken string
       must not be able to widen the panel. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.chat-msg--mine .chat-bubble {
    border-radius: 12px 12px 3px 12px;
    background: var(--c-primary);
    border-color: var(--c-primary);
    color: #fff;
}

.chat-msg__when {
    margin-top: 2px;
    font-size: 10px;
    color: var(--c-ink-4);
}

.chat-composer {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 10px;
    border-top: 1px solid var(--c-line-soft);
    background: #fff;
}

.chat-input {
    flex: 1 1 auto;
    min-width: 0;
    max-height: 96px;
    padding: 8px 10px;
    border: 1px solid var(--c-line);
    border-radius: 8px;
    font: inherit;
    font-size: var(--fs-sm);
    color: var(--c-ink);
    resize: none;
}

.chat-input:focus {
    outline: none;
    border-color: var(--c-primary);
}

.chat-send {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 8px;
    background: var(--c-primary);
    color: #fff;
    cursor: pointer;
    transition: opacity 0.15s;
}

.chat-send:disabled {
    opacity: 0.45;
    cursor: default;
}

.chat-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 28px 16px;
    text-align: center;
    color: var(--c-ink-4);
    font-size: var(--fs-sm);
}

.chat-empty i { font-size: var(--fs-2xl); }

@media (max-width: 480px) {
    /* Nearly the whole screen on a phone - a 340px panel on a 360px screen
       leaves a sliver of page either side that only gets clicked by mistake. */
    .chat-panel {
        position: fixed;
        top: var(--app-header-h, 88px);
        right: 8px;
        left: 8px;
        width: auto;
        max-width: none;
        height: calc(100vh - var(--app-header-h, 88px) - 16px);
    }
}


/* ═══════════════════════════════════════════════════
   The shortcut key at the right-hand end of a panel row, as Windows shows one
   beside a menu item: plain and quiet, with the name taking the space that is
   left.

   Shown inside the panels only. A key printed beside "Orders" in the bar
   itself would be width taken from the names on that row for something the
   tooltip and the shortcuts page already say, and width in the bar is the one
   thing this whole layout is careful with. The keys still work, and every menu
   that has one carries it in its tooltip.
   ═══════════════════════════════════════════════════ */
.tnav-key {
    flex: 0 0 auto;
    margin-left: auto;
    /* The row's own gap already separates it from the name; this is only the
       floor, so a long name and a long key (Ctrl+Alt+T) still fit side by
       side instead of the name wrapping. */
    padding-left: 8px;
    /* The menu's own typeface, not monospace: a different font beside the name
       is what made the pair look mismatched. Smaller, lighter and faded so it
       reads as a hint after the name rather than part of it. */
    font-family: inherit;
    font-size: 10px;
    font-weight: 400;
    letter-spacing: 0.01em;
    color: var(--c-ink-3, #8a7f75);
    opacity: 0.7;
    white-space: nowrap;
    /* The row is the click target; the key is a label on it. */
    pointer-events: none;
}

/* Stay quiet on the highlighted row too - just follow the row's own colour so
   it never turns into a clash on the coloured background. */
.tnav__link:hover .tnav-key,
.tnav__link.is-active .tnav-key {
    color: inherit;
    opacity: 0.65;
}
