/* ============================================================================
   TMA DESIGN SYSTEM — SHELL CHROME
   Ported from the design prototype's assets/css/components.css (the app bar,
   identity button, bottom nav + desktop rail, workspace drawer and menu
   popover blocks) under the §3 fidelity mandate.

   The app bar is always on, on every surface, and NEVER restyles between areas
   (DESIGN-SYSTEM §4). That sentence is the reason the host's per-route header
   overrides come out rather than get layered over: an override that only fires
   on /app or /admin is, by definition, the bar restyling between areas.

   SHELL ROOT — the prototype's surface-state classes (rail-desktop, has-rail,
   has-workdrawer, drawer-open) sit on <body> there, because every prototype
   screen is a flat document whose bar and nav are body children. On this host
   the shell has a real root element, and the state is known when that element
   renders but NOT when <body> does — <body> is written by App.razor, before the
   layout has resolved who is signed in, and the surface depends on exactly that
   (the /admin/* namespace holds both the platform console and the operator's
   own workspace pages, so no path rule can tell them apart). Keying off <body>
   would therefore mean stamping the class from JS after first paint, and a
   desktop workbench page would visibly reflow as its 220px rail gutter arrived.
   So the same correction §7 already applies to the gutter applies here: the
   rules key off .tma-shell, the shell's own root. Every element they reach —
   the fixed nav, the drawer, the content column — is inside it, so nothing
   about the cascade changes; only the ancestor is named honestly.
   ========================================================================== */

/* ---- app bar (always-on, contextual — never disappears, never restyles) --- */
.tma-appbar {
  position: sticky; top: 0; z-index: var(--z-appbar);
  height: var(--appbar-h);
  display: flex; align-items: center; gap: var(--sp-4);
  padding-inline: var(--gutter);
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hairline);
}
.tma-appbar .brand {
  display: flex; align-items: center; gap: var(--sp-icon-text);
  font-weight: 900; letter-spacing: -.01em; color: var(--ink-1);
  font-size: var(--t-16); text-decoration: none;
  min-width: 0;                       /* lets the wordmark be the thing that truncates, not the mark */
}
.tma-appbar .brand > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tma-appbar .brand:hover { text-decoration: none; }
.tma-appbar .brand .mark { width: 26px; height: 26px; border-radius: 7px; object-fit: contain; }
/* MEASURED at 375px in the running host: the brand mark laid out 22.19x26 and the identity mark 7.52x26
   — squashed, not sized. An SVG in a flex row still has flex-shrink: 1, so `width` is a starting size,
   not a floor. The prototype never shows this because its bar carries no drawer burger, leaving ~40px
   of slack at 375; this host's bar does. The design's own answer is one line up in its icons section
   (`.icon { flex: none }`), so the marks take the same treatment. The wordmark is what should give — it
   truncates; a logo that renders a third of its width is just broken. */
.tma-appbar .mark { flex: none; }
/* OWNER RULING 2026-08-13 #3 — the flex: none above stopped the marks from SQUASHING, and shipped; what it
   could not do is make room. MEASURED at 375px on production (build cf4b7d5, which already carries it):
   both marks laid out a true 26x26, and the wordmark was the thing that gave — clientWidth 79 against a
   scrollWidth of 123, i.e. "That Menu App" ellipsised down to about "That Menu…". That is the defect as the
   owner sees it: the brand NAME cut off by a symbol, twice over, since the guest identity button repeats
   the same mark. The ruling settles the trade-off the §9.1 comment left open — the WORDMARK wins — so on a
   phone the marks stand down and the name renders whole. 34px each (26 + the icon-text gap) buys 68px,
   against the 44px the wordmark was short. Above 600px the bar has the room and the mark returns; the bar
   is not "restyling between areas" (DESIGN-SYSTEM §4) — this is one viewport rule applied on every one. */
@media (max-width: 600px) {
  .tma-appbar .brand .mark, .tma-appbar .identity-btn .mark { display: none; }
  /* NEW.4 (owner ruling 2026-08-15): the mobile bar crammed concept name + location into the same row as
     the burger and the identity button. The wordmark's squash fix above is now moot on mobile — the brand
     link is dropped entirely there; the drawer's own .drawer-logo already carries it every time the
     hamburger is reachable, which is every mobile screen. Dropping .brand also buys back the room the
     08-13 ruling was fighting over, so the context label gets its own full-width row instead of fighting
     for the same line: the bar wraps, and forcing .context to a 100% flex-basis (after the 0-order burger/
     spacer/identity) always pushes it onto its own line under the controls row, whatever the operator's
     concept-name length. Desktop (>600px) is untouched — none of these rules apply above this query. */
  .tma-appbar { flex-wrap: wrap; height: auto; min-height: var(--appbar-h); row-gap: 0; padding-block: var(--sp-2); }
  .tma-appbar .brand { display: none; }
  .tma-appbar .context {
    order: 5;
    flex: 1 0 100%;
    text-align: left;
    padding-block-start: var(--sp-1);
  }
}
.tma-appbar .context {
  font-size: var(--t-14); color: var(--ink-3); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tma-appbar .spacer { flex: 1; }
.tma-appbar .icon-btn {
  display: grid; place-items: center;
  /* The burger squashed for the same reason the marks did: MEASURED 31.63px wide at 375px, against the
     --touch floor below. A tap target quietly under the minimum, not a narrow icon. */
  flex: none;
  width: var(--touch); height: var(--touch);
  border-radius: var(--radius-sm);
  color: var(--ink-2); background: none; border: none;
}
.tma-appbar .icon-btn:hover { background: var(--surface-2); color: var(--ink-1); }

/* the Guest / identity button (owner ruling 07-23) */
.tma-appbar .identity-btn {
  display: inline-flex; align-items: center; gap: var(--sp-icon-text);
  height: 40px; padding-inline: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--hairline-strong);
  background: var(--surface);
  color: var(--ink-1); font-weight: 700; font-size: var(--t-14);
  box-shadow: var(--elev-1);
}
.tma-appbar .identity-btn .avatar {
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent-strong); color: var(--accent-on-strong);
  font-size: var(--t-cap); font-weight: 800;
}
/* A guest gets the MARK where a signed-in person gets the .avatar (identityContent()), so it takes the
   avatar's size. NOT in the prototype, and that is the point: measured at 375px on the running
   prototype, its guest mark lays out at 0×0 — the sheet sizes .appbar .brand .mark but never
   .identity-btn .mark, so the guest branch emits a mark nothing can see. Porting the CSS verbatim would
   reproduce an invisible element the design's own code deliberately renders. Reported to the design lane
   (SHELL.7 §9) rather than silently matched or silently diverged from. */
.tma-appbar .identity-btn .mark { width: 26px; height: 26px; border-radius: 7px; object-fit: contain; }

/* ---- icons — one system: 1.8px-stroke line icons in brand colors ----------- */
/* Ported alongside the chrome because the chrome CANNOT render without it: the blocks below size
   .icon inside the bottom nav and the drawer title, but the rule that makes an .icon a line icon at all
   — stroke, no fill — lives in the prototype's icons section. Without it every ported glyph paints as a
   solid black silhouette. Scoped-descendant rules elsewhere in this file (0,2,0) still out-rank it. */
.icon {
  width: 20px; height: 20px;
  stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  fill: none; flex: none;
}
.icon-btn .icon { width: 20px; height: 20px; }

/* ---- bottom navigation (mobile) + desktop rail ----------------------------- */
.tma-bottomnav {
  position: fixed; inset-inline: 0; bottom: 0; z-index: var(--z-bottomnav);
  height: calc(var(--bottomnav-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  display: flex; align-items: stretch; justify-content: space-around;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--hairline);
}
.tma-bottomnav a, .tma-bottomnav button {
  flex: 1 1 0; max-width: 120px; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; min-height: var(--touch);
  color: var(--ink-3); font-size: var(--t-cap); font-weight: 700;
  text-decoration: none;
  background: none; border: none;
}
/* OWNER RULING 2026-08-13 #1 — the icons and labels in this bar did not line up. MEASURED at 375px on the
   running site: a slot is ~72px wide, so "For Restaurants" and "Find food near you" each wrapped to two
   lines (label box 38.38px) while "Pricing", "Suppliers" and "You" stayed on one (19.19px). The item is a
   centre-justified column, so a two-line label pushes its OWN icon up — the long slots' icons laid out at
   y=1139.31 against the short ones' y=1148.91. Two rules answer it, and both are needed:
   the words got shorter (ShellNavCatalog.MaxSlotLabelLength, which is the real fix and matches the
   prototype's NAVS.www), and the row is now held to one line here so a future long label — or a locale
   whose translation runs long — degrades to an ellipsis instead of staggering every icon beside it.
   `flex: 1 1 0` + `min-width: 0` above is the other half: with `flex: 1` the basis was the label's own
   width, so the slots were unequal (77.45px vs 71.88px) and never sat on the design's even rhythm. */
.tma-bottomnav a > span, .tma-bottomnav button > span {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tma-bottomnav a:hover { text-decoration: none; }
.tma-bottomnav .icon { width: 22px; height: 22px; }
.tma-bottomnav .is-active { color: var(--accent-fg); }
.tma-bottomnav .is-active .icon { stroke: var(--accent-fg); }

/* desktop: on rail surfaces (.tma-shell.rail-desktop — every patron page per the
   studio pick, plus business pages) the same destinations become a left rail;
   the user menu stays bottom-anchored. Business pages layer the workspace
   DRAWER on top and hide this rail at desktop — see .has-workdrawer below. */
@media (min-width: 1280px) {
  .tma-shell.rail-desktop .tma-bottomnav {
    inset: var(--appbar-h) auto 0 0; width: 220px; height: auto;
    flex-direction: column; justify-content: flex-start;
    padding: var(--sp-4) var(--sp-2);
    border-top: none; border-inline-end: 1px solid var(--hairline);
    gap: var(--sp-nav-item);
  }
  .tma-shell.rail-desktop .tma-bottomnav a, .tma-shell.rail-desktop .tma-bottomnav button {
    flex: none; max-width: none; width: 100%;
    flex-direction: row; justify-content: flex-start;
    gap: var(--sp-icon-text); padding-inline: var(--sp-4);
    min-height: var(--touch); border-radius: var(--radius-sm);
    font-size: var(--t-14);
  }
  .tma-shell.rail-desktop .tma-bottomnav .is-active { background: var(--accent-soft); }
  /* The rail's gutter goes on the CONTENT COLUMN, never on the shell root — §7. */
  .tma-shell.rail-desktop .tma-shell-main { padding-inline-start: 220px; }
}

/* ---- the workspace drawer (business surface, studio pick) ------------------ */
.tma-workdrawer {
  position: fixed; z-index: var(--z-drawer);
  top: var(--appbar-h); bottom: 0; inset-inline-start: 0;
  width: min(300px, 86vw);
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface);
  /* SHELL.6 — the panel's ink, so anything inside it that is NOT .wd-link markup still reads correctly.
     On this host the drawer's contents are the platform's own nav map, and the rule that used to colour
     them carried a FIXED light-theme token onto this theme-aware surface: MEASURED 2.91:1 in dark, below
     AA, on every link. --ink-2 is the same secondary ink .wd-link already uses, and is defined per theme
     rather than patched after the fact — 8.92:1 dark, 7.56:1 light. */
  color: var(--ink-2);
  border-inline-end: 1px solid var(--hairline);
  box-shadow: var(--elev-3);
  padding: var(--sp-3) var(--sp-3) calc(var(--bottomnav-h) + var(--sp-4));
  transform: translateX(calc(-102% * var(--flip)));
  transition: transform var(--dur) var(--ease);
}
.tma-shell.drawer-open .tma-workdrawer { transform: none; }
.tma-shell.drawer-open .tma-workdrawer-scrim { display: block; }

/* F-425 — the drawer's INTERIOR on a route with no circuit — MOVED, and deliberately not kept here.
   The four `!important` overrides that used to sit at this spot forced MudBlazor's grid-animated collapse
   open on statically rendered routes, where MudNavGroup's expansion is circuit state and MEASURED 8 of 15
   destinations were unreachable with the drawer standing open. There are no MudNavGroups left inside
   .tma-workdrawer: the groups are TmaDrawerGroup now, so the rule belongs to that component and lives in
   TmaDrawerGroup.razor.css, where it is two ordinary declarations against its own `hidden` attribute
   instead of four `!important`s against a framework's internals.

   Left as a comment rather than deleted silently, because the RULE it encoded is still binding and is
   easy to lose in a move: on a route with no circuit every group renders open and the caret goes, which
   is also the design's own shape (§9.9 — the prototype's .wd-group is a flat titled list, always
   expanded). Deleting the selectors without carrying the behaviour would restore the unreachable
   destinations and nothing would fail. */

/* The drawer BODY. The design's panel is a stack of .wd-group and nothing else — the per-group and
   per-row rules live in TmaDrawerGroup.razor.css / TmaDrawerLink.razor.css, scoped to their own
   components, which is what keeps two port chips out of one another's stylesheet. */
.tma-workdrawer .drawer-nav {
  display: flex;
  flex-direction: column;
}
.tma-workdrawer-scrim {
  position: fixed; inset: 0; z-index: calc(var(--z-drawer) - 1);
  display: none;                            /* visible only while the drawer is open (R50) */
  background: var(--scrim);
}
/* The `.wd-link` / `.wd-group` / `.wd-title` block that stood here is GONE, and where it went matters
   more than that it moved. It is now TmaDrawerGroup.razor.css and TmaDrawerLink.razor.css, scoped to
   the components that emit those classes.

   Until SHELL.8 nothing on this platform emitted a single one of them. The block was ported with the
   rest of the chrome and sat here for a release styling markup that did not exist — a stylesheet
   merged ahead of the markup that exercises it, which is unfalsifiable by construction and is the
   generalised lesson PORT-BACK-BRIEF §9.1 wrote down after the last time. It is worth naming plainly:
   this file's own CSS-half commit shipped, deployed and was verified as SERVED with the right token
   values, and none of that could tell anyone the rules reached nothing.

   Leaving a second copy here would be worse than the original problem, because an unscoped rule
   outranks a scoped one on identical specificity by source order, so shell.css would quietly own the
   look while the component sheet appeared to. DrawerComponentVocabularyTests asserts the absence.

   `.wd-dash` — the prototype's prominent home row — went with it and has NO component yet, because no
   platform surface renders one. It belongs on TmaDrawerLink as a variant on the day a surface needs it,
   not here waiting for it. */

@media (min-width: 1280px) {
  /* the drawer IS the desktop navigation on business pages: sticky open,
     collapsible, no scrim — and the thin 4-slot rail stands down for it */
  .tma-shell.has-workdrawer .tma-bottomnav { display: none; }
  .tma-shell.has-workdrawer .tma-workdrawer { box-shadow: none; z-index: var(--z-rail); }
  .tma-shell.has-workdrawer .tma-workdrawer-scrim { display: none; }

  /* SHELL.6 — THE DESKTOP-OPEN DEFAULT, and the reason it lives here rather than in C#.
     The prototype opens the drawer at mount with `setOpen(desktop() && pref !== "closed")`, because a
     browser knows its own viewport. The server does not, and both ways of telling it are worse than
     not needing it: asking JS before first paint costs a visible reflow at 1280 (the drawer paints
     closed, then snaps open), and remembering the answer costs a write on a load path that runs TWICE
     under Blazor prerendering (F-386).

     So the media query IS the default, and the class carries only the EXPLICIT override — the same
     tri-state the prototype stores in DB.pref("workdrawer"): absent / open / closed. Gated with
     :not() rather than written as an unconditional `transform: none` plus a later override, so an
     explicit close wins by not matching this rule at all — there is no specificity race to lose, and
     no state in which both rules claim the drawer. ShellDrawerState.IsOpen is the C# statement of
     exactly this rule, and ShellChromeCssTests holds the two together. */
  .tma-shell.has-workdrawer:not(.drawer-closed) .tma-workdrawer { transform: none; }

  /* §7, the app-bar full-bleed rule — implemented as the rule STATES it rather
     than as the prototype had to implement it.
     The prototype reserves the drawer's gutter on the document body and then
     negates it back off the bar, because there every page is a flat document
     and the bar is a body child. The brief's own wording is the correction: "The drawer's
     reserved gutter belongs on the content column, never on the shell root —
     putting it on the root indents the bar and leaves a blank corner in both drawer states."
     This host renders the bar and the content as siblings inside the shell, so
     the gutter can go straight onto the content column and the bar spans the
     viewport with nothing to negate. Same result, one rule instead of two, and
     the failure mode the note warns about cannot occur. Inline-direction
     properties throughout, so it mirrors correctly under RTL.

     R45 — note the selector carries no open/closed state: the gutter is
     RESERVED either way, so toggling the drawer never shifts the page left and
     right, and .area-wrap (margin auto) keeps centering inside what is left.

     It must also out-rank the rail rule above, which sets 220px on the same
     element at the same specificity — source order is doing that work, so this
     block stays BELOW the rail block. */
  .tma-shell.has-workdrawer .tma-shell-main { padding-inline-start: min(300px, 86vw); }
}

/* ---- user menu / generic menu popover -------------------------------------- */
.tma-menu-pop {
  position: absolute; z-index: var(--z-popover);
  min-width: 240px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--elev-3);
  padding: var(--sp-2);
}
.tma-menu-pop .menu-item {
  display: flex; align-items: center; gap: var(--sp-icon-text);
  width: 100%; min-height: var(--touch);
  padding-inline: var(--sp-3);
  border-radius: var(--radius-sm);
  color: var(--ink-1); font-size: var(--t-14); font-weight: 600;
  text-decoration: none;
}
.tma-menu-pop .menu-item:hover { background: var(--surface-2); text-decoration: none; }
.tma-menu-pop .menu-sep { border-top: 1px solid var(--hairline); margin: var(--sp-2) 0; }
.tma-menu-pop .menu-head {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--t-cap); font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3);
}

/* F-592/fb0818m-06 (dark-mode-crawl-1, NEW.3): the theme picker's trailing checkmark (F-597 — ships in
   EVERY radio, a class flip alone moves it). Lives here, NOT in TmaUserMenu.razor.css: that sheet's
   scope attribute never reaches <TmaIcon>'s own rendered <svg> (a child component across an assembly
   boundary), so a scoped copy of this rule could never match anything and both rows kept a visible
   tick regardless of which theme was active (owner report, 2026-08-18, item 5). An unscoped rule needs
   no scope attribute on the target element at all. */
.tma-menu-pop .menu-tick { margin-inline-start: auto; }
.tma-menu-pop [data-theme-mode]:not(.is-current) .menu-tick { display: none; }

/* F-592/fb0818m-06, item 5: every row in the popover shares ONE left inset. .menu-item/.menu-head get
   theirs from padding-inline (above); a bare form control dropped in beside them (the language select,
   TmaUserMenu.razor NEW.3's TmaSelect migration) carries none of its own, so without this it sits flush
   at the popover's OWN --sp-2 padding — narrower than every other row's --sp-2 + --sp-3. */
.tma-menu-pop .field { padding-inline: var(--sp-3); }

/* ---- the shell's own content column ---------------------------------------- */
/* The bar is sticky and in normal flow, so it occupies its own height and the
   content needs no offset for it — the MudMainContent appbar padding that used
   to supply that offset is now double-counting and comes off. */
.tma-shell-main { padding-top: 0; }
.tma-shell-main > .tma-shell-canvas { padding-bottom: var(--bottomnav-h); }
@media (min-width: 1280px) {
  .tma-shell.has-workdrawer .tma-shell-main > .tma-shell-canvas { padding-bottom: 0; }
}

/* ---- the site footer's brand lockup ---------------------------------------- */
/* OWNER RULING 2026-08-13 #2 — on a phone the footer's logo was a 46px tile pinned to the top-left corner
   of a centred block. The centring rule for the mobile footer already existed (app.css, max-width: 560px,
   justify-items: center) but could not reach the logo: `.footer-logo { justify-self: start }` from the
   desktop grid outranks a container-level justify-items and was never reset, so the logo alone stayed left
   while the tagline, links and language control centred around it. MEASURED at 375px on production: logo
   x=16 w=46 inside a 365px-wide centred footer.
   The ruling sets the size too — at least as wide as the "Find your menu" button above it, which measures
   325px at 375 (it fills the content column). So the logo fills the column as well, capped so it cannot run
   away at the top of the range, and the desktop lockup beside the tagline is left exactly as it was.
   These rules live here rather than in app.css because that sheet is at its 350 KiB pre-commit budget;
   shell.css loads after it, so the same specificity still wins.
   F-700 (owner mobile screenshot): justify-self above centres the BOX in its grid column, but the box
   itself (display: inline-flex, app.css) had no justify-content — so once width: min(100%, 21rem) makes
   the box wider than its own content (the <img>, capped at 168px), the image sits pinned to the box's
   flex-start edge instead of centred within it. The box centres; its content did not. justify-content
   below is the other half — desktop never needs it, because .footer-logo there is width: fit-content
   (app.css, unconditional) and always equals its content's width, leaving no slack to distribute. */
@media (max-width: 560px) {
  .site-footer .footer-logo {
    justify-self: center;
    justify-content: center;
    width: min(100%, 21rem);
  }
  .site-footer .footer-logo img { width: 100%; max-width: 100%; height: auto; }
}
