/* ══════════════════════════════════════════════════════════════════════════════
   Tribun RIAS — top navigation bar
   ─────────────────────────────────────────────────────────────────────────────
   ONE stylesheet for ONE partial (templates/partials/_topbar.html), loaded by every
   app page including the superadmin shell. The bar used to be hand-copied into seven
   templates with two competing CSS definitions, which is how the dropdown drifted
   apart page to page. Anything visual about the bar belongs here and nowhere else.

   The look is a neumorphism / glassmorphism hybrid, built only from this platform's
   own tokens (--glass, --surface-*, --accent-*, --shadow-*):

     · GLASS  — the bar itself and every raised element: translucent fill plus a real
                backdrop blur, so page content shows through and moves under it.
     · NEUMO  — depth comes in matched pairs. The nav rail is a pressed TROUGH (inset
                dark + inset light). The active item is an extruded KEY (outer drop +
                inset top highlight). Same light source, opposite directions.

   Hover is meant to feel immersive rather than decorative: a cursor-tracked spotlight
   travels inside the rail (--mx/--my are written by topbar.js), the hovered item lifts,
   its icon scales, and an accent bloom fades up behind it. Every duration is scaled by
   --motion, which is the one global lever on interaction timing — there is no
   prefers-reduced-motion path any more (see the policy note at the end of tokens.css).
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── shell ─────────────────────────────────────────────────────────────────────
   Centring the rail took two goes, and both failure modes are worth naming:

     · plain `1fr auto 1fr` — a side whose CONTENT is wider than its track makes that
       track grow and shoves the centre column along. The admin alerts bell did exactly
       that and pushed the nav 42px off centre.
     · pinning the rail at left:50% out of flow — dead centre, but the sides then know
       nothing about it, so a wide right cluster slides straight under it. The preview
       page's deck chip + Decks + Download overlapped the rail by 24px.

   `minmax(0, 1fr)` fixes both: the auto-minimum is removed, so the two side tracks stay
   exactly equal no matter what they hold, the centre track is therefore always centred,
   and because they are real tracks nothing can overlap. Sides that would outgrow their
   share shed their lowest-value item instead (see .tb-has-extras). */
.topbar {
  position: sticky; top: 0; z-index: 90;
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 16px; padding: 11px 24px; flex-shrink: 0;

  background: var(--glass);
  -webkit-backdrop-filter: blur(26px) saturate(1.7);
          backdrop-filter: blur(26px) saturate(1.7);
  border-bottom: 1px solid var(--glass-brd);
  /* neumorphic pair: soft cast below, crisp light catch along the top edge */
  box-shadow: 0 10px 30px -22px rgba(14, 18, 48, 0.30),
              inset 0 1px 0 color-mix(in srgb, #fff 62%, transparent);
}
[data-theme="dark"] .topbar {
  box-shadow: 0 12px 34px -22px rgba(0, 0, 0, 0.70),
              inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent);
}
/* Browsers without backdrop-filter would show text over raw page content. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar { background: var(--surface); }
}

.tb-left  { display: flex; align-items: center; gap: 12px; min-width: 0; }
.tb-mid   { display: flex; justify-content: center; min-width: 0; }
.tb-right { display: flex; align-items: center; gap: 9px; justify-content: flex-end; min-width: 0; }

/* A page that adds its own bar content (preview actions, admin alerts) drops the inline
   name/role: it is the least useful thing there — the account dropdown already shows name,
   email and role — and keeping it made the right track outgrow its share. */
.topbar.tb-has-extras .tb-who { display: none; }

/* ── brand lockup ──────────────────────────────────────────────────────────────
   No "Report Intelligence System" strap and no badge around RIAS. The lockup reads
   as one considered unit instead: the mark, a hairline, then RIAS set in the mono
   face with wide tracking — a system designator, which is what RIAS actually is.
   A pill would date the mark; tracked mono sits with the rest of the 2026 palette. */
.tb-brand {
  display: inline-flex; align-items: center; gap: 11px;
  text-decoration: none; padding: 4px 8px 4px 4px; border-radius: var(--r-sm);
  transition: transform calc(.26s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1);
}
.tb-mark {
  position: relative; width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center;
  /* neumorphic seat for the mark: raised off the glass, lit from above */
  box-shadow: 0 2px 6px -2px rgba(14, 18, 48, 0.28),
              inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent);
  transition: box-shadow calc(.3s * var(--motion, 1)) ease;
}
.tb-mark img { display: block; width: 32px; height: 32px; border-radius: 50%; }
/* accent halo blooms out of the mark on hover — the brand's own gradient, not a glow effect */
.tb-mark::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  background: var(--accent-grad); opacity: 0; z-index: -1; filter: blur(7px);
  transition: opacity calc(.34s * var(--motion, 1)) ease;
}
.tb-brand:hover .tb-mark::after { opacity: .5; }
.tb-brand:hover .tb-mark {
  box-shadow: 0 4px 12px -3px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 80%, transparent);
}

/* Two words, one lockup, so they share a BASELINE and their CAPITALS are the same height.
   line-height: 1 on both is what makes that work: with the default line box each span was
   taller than its glyphs by a different amount, so centring the boxes did not put the words
   on a common baseline. The rule has no text, so it centres on its own. */
.tb-word { display: inline-flex; align-items: baseline; gap: 9px; }
.tb-word-1 {
  font-family: var(--font-ui); font-size: 15.5px; font-weight: 600; line-height: 1;
  letter-spacing: -.018em; color: var(--ink); white-space: nowrap;
}
/* the hairline replaces the badge: it separates without enclosing */
.tb-word-rule {
  width: 1px; height: 15px; flex-shrink: 0; align-self: center;
  background: linear-gradient(180deg, transparent, var(--rule-2) 22%, var(--rule-2) 78%, transparent);
}
/* 14.5px, not 11px. Cap height is what the eye compares, and Geist Mono's caps are ~0.726 of
   its font size against ~0.719 for Geist — so 11px mono put RIAS's capitals at 8.0px beside
   Tribun's 11.1px, i.e. 28% shorter, which read as a mistake rather than as hierarchy. At
   14.5px the caps land at ~10.5px, a deliberate hair under Tribun. Tracking comes down from
   .17em so the wider glyphs do not stretch the lockup. */
.tb-word-2 {
  font-family: var(--font-mono); font-size: 14.5px; font-weight: 600; line-height: 1;
  letter-spacing: .11em; text-transform: uppercase; white-space: nowrap;
  color: var(--accent-ink);
  /* the tracking adds space after the final S; trim it so the lockup's right edge is optical */
  margin-right: -.11em;
}
/* ── centred nav rail ──────────────────────────────────────────────────────────
   The rail is the PRESSED half of the neumorphic pair: content sits down inside it.
   SQUARED, not a capsule: a 999px rail full of 999px keys was the largest pill on the
   platform, and pill geometry is banned. The depth reading is unchanged — a trough holding a
   raised key — because depth comes from the shadows, never from the corner radius. */
.tb-nav {
  position: relative; display: flex; align-items: center; gap: 3px;
  padding: 4px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--surface-3) 70%, transparent);
  border: 1px solid color-mix(in srgb, var(--rule) 70%, transparent);
  box-shadow: var(--neu-in);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  max-width: 100%;
}
/* the immersive part: a spotlight that follows the pointer across the whole rail.
   Painted under the links, so it reads as light travelling beneath the glass. */
.tb-nav::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(150px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--accent-solid) 20%, transparent), transparent 72%);
  opacity: 0; transition: opacity calc(.4s * var(--motion, 1)) ease;
}
.tb-nav:hover::before { opacity: 1; }

.tb-link {
  position: relative; display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: var(--r-xs);
  font-size: 13.2px; font-weight: 500; line-height: 1;
  color: var(--muted); text-decoration: none; white-space: nowrap;
  transition: color calc(.2s * var(--motion, 1)) ease,
              transform calc(.26s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1);
}
.tb-link svg {
  width: 15px; height: 15px; flex-shrink: 0;
  transition: transform calc(.28s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1);
}
/* the bloom behind a hovered link — separate layer so it can fade independently of colour */
.tb-link::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1;
  background: var(--glass-2);
  box-shadow: 0 3px 10px -4px rgba(14, 18, 48, 0.22),
              inset 0 1px 0 color-mix(in srgb, #fff 60%, transparent);
  opacity: 0; transform: scale(.9);
  transition: opacity calc(.24s * var(--motion, 1)) ease,
              transform calc(.3s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1);
}
.tb-link:hover { color: var(--ink); transform: translateY(-1px); }
.tb-link:hover::before { opacity: 1; transform: scale(1); }
.tb-link:hover svg { transform: scale(1.12); }
.tb-link:active { transform: translateY(0); }
.tb-link:focus-visible { outline: 2px solid var(--accent-solid); outline-offset: 2px; }

/* active = the EXTRUDED half of the pair: raised out of the trough, accent-lit */
.tb-link.active {
  color: var(--accent-ink); font-weight: 600;
  background: var(--surface);
  box-shadow: 0 3px 10px -3px color-mix(in srgb, var(--accent-solid) 34%, transparent),
              0 1px 2px rgba(14, 18, 48, 0.10),
              inset 0 0 0 1px color-mix(in srgb, var(--accent-solid) 30%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 75%, transparent);
}
[data-theme="dark"] .tb-link.active {
  background: color-mix(in srgb, var(--surface-3) 92%, transparent);
  box-shadow: 0 3px 12px -4px var(--accent-glow),
              inset 0 0 0 1px color-mix(in srgb, var(--accent-solid) 38%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 9%, transparent);
}
.tb-link.active::before { opacity: 0; }
.tb-link.active:hover { transform: none; }
/* No seat under the active item. The raised key (surface face + accent-lit shadow) and the accent
   ink already say which page you are on; the extra 2px bar read as a third, competing marker. */
.tb-link.admin.active { color: var(--accent-ink); }

/* ── right cluster ─────────────────────────────────────────────────────────── */
.tb-icon {
  width: 34px; height: 34px; border-radius: var(--r-sm); flex-shrink: 0;
  display: grid; place-items: center; color: var(--muted);
  background: color-mix(in srgb, var(--surface-3) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--rule) 70%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
  transition: color calc(.18s * var(--motion, 1)) ease,
              box-shadow calc(.24s * var(--motion, 1)) ease,
              transform calc(.24s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1);
}
.tb-icon:hover {
  color: var(--accent-ink); transform: translateY(-1px);
  box-shadow: 0 4px 12px -4px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent);
}
.tb-icon:focus-visible { outline: 2px solid var(--accent-solid); outline-offset: 2px; }

.tb-who { text-align: right; line-height: 1.25; min-width: 0; }
.tb-who-name {
  font-size: 12.6px; font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 170px;
}
.tb-who-role {
  font-family: var(--font-mono); font-size: 9.2px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}

/* ── avatar + dropdown ─────────────────────────────────────────────────────── */
.tb-user { position: relative; flex-shrink: 0; }
.tb-avatar {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
  color: #fff; background: var(--accent-grad);
  box-shadow: 0 3px 10px -3px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 45%, transparent);
  transition: transform calc(.26s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1),
              box-shadow calc(.26s * var(--motion, 1)) ease;
}
.tb-avatar:hover { transform: translateY(-1px) scale(1.04); box-shadow: 0 6px 18px -4px var(--accent-glow); }
.tb-avatar:focus-visible { outline: 2px solid var(--accent-solid); outline-offset: 2px; }

/* Hamburger — the avatar's phone counterpart, holding Profile, Admin, appearance and sign out.
   display:none here and grid in the phone block, so the two triggers are never both present. */
.tb-burger {
  display: none; width: 38px; height: 38px; border-radius: var(--r-sm); flex-shrink: 0;
  place-items: center; color: var(--ink-2);
  background: color-mix(in srgb, var(--surface-3) 60%, transparent);
  border: 1px solid color-mix(in srgb, var(--rule) 72%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
  transition: color calc(.18s * var(--motion, 1)) ease,
              box-shadow calc(.24s * var(--motion, 1)) ease;
}
.tb-burger svg { width: 20px; height: 20px; }
.tb-burger:hover { color: var(--accent-ink); }
/* pressed-in while its menu is open: the trough is the same "held down" reading the nav uses */
.tb-user.open .tb-burger { color: var(--accent-ink); box-shadow: var(--neu-in-sm); }
.tb-burger:focus-visible { outline: 2px solid var(--accent-solid); outline-offset: 2px; }
/* current page is one this menu owns (Profile / Admin) — the same accent-ring-and-ink reading the
   dock's active key uses, so "where am I" is answered on those screens too */
.tb-burger.here {
  color: var(--accent-ink);
  background: var(--surface);
  box-shadow: 0 3px 10px -3px color-mix(in srgb, var(--accent-solid) 34%, transparent),
              inset 0 0 0 1px color-mix(in srgb, var(--accent-solid) 30%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent);
}
[data-theme="dark"] .tb-burger.here {
  background: color-mix(in srgb, var(--surface-3) 92%, transparent);
  box-shadow: 0 3px 12px -4px var(--accent-glow),
              inset 0 0 0 1px color-mix(in srgb, var(--accent-solid) 38%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 9%, transparent);
}

.tb-menu {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 120;
  width: 254px; padding: 7px; border-radius: var(--r-md);
  background: var(--glass);
  -webkit-backdrop-filter: blur(28px) saturate(1.8);
          backdrop-filter: blur(28px) saturate(1.8);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--shadow-lg), inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
  /* animated open rather than display:none, so it eases in from the avatar */
  opacity: 0; transform: translateY(-6px) scale(.97); transform-origin: top right;
  pointer-events: none; visibility: hidden;
  transition: opacity calc(.2s * var(--motion, 1)) ease,
              transform calc(.28s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1),
              visibility 0s linear calc(.2s * var(--motion, 1));
}
.tb-user.open .tb-menu {
  opacity: 1; transform: translateY(0) scale(1);
  pointer-events: auto; visibility: visible; transition-delay: 0s;
}

.tb-menu-head {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px 11px; border-bottom: 1px solid var(--rule); margin-bottom: 6px;
}
/* flex: 1 so the identity column claims all the room left beside the disc — left to its
   own content size it laid out at 116px inside 188px of space (measured), which pushed the
   email into an overflow it did not need. min-width: 0 lets it shrink below content when
   the menu itself is narrow. */
.tb-menu-id { flex: 1 1 auto; min-width: 0; }
/* the identity disc, shown only where the bar has no avatar (phones) */
.tb-menu-ava {
  display: none; width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0;
  place-items: center; font-size: 12px; font-weight: 700; letter-spacing: .02em;
  color: #fff; background: var(--accent-grad);
  box-shadow: 0 3px 10px -3px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 45%, transparent);
}
.tb-menu-name  { font-size: 13.5px; font-weight: 600; color: var(--ink); }
/* WRAPS, never ellipsises. An address is not a decorative label — "data@tribunnew…" is
   worse than two lines, and the identity disc beside it narrowed this column to 116px
   against the 142px this address needs (measured). No text in this platform gets cut. */
.tb-menu-mail  { font-size: 11.5px; color: var(--muted); margin-top: 2px;
                 white-space: normal; overflow-wrap: anywhere; line-height: 1.35; }
.tb-menu-role  { font-family: var(--font-mono); font-size: 9.2px; font-weight: 700;
                 letter-spacing: .1em; text-transform: uppercase;
                 color: var(--accent-ink); margin-top: 5px; }

/* appearance switch — light/dark now lives in here, not as a bar icon */
.tb-appear { padding: 3px 4px 7px; }
.tb-appear-lab {
  font-size: 9.4px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); padding: 0 7px 6px;
}
/* grid-auto-columns rather than a hard-coded `1fr 1fr`. Appearance only has two options now, but the
   retired three-option Motion switch wrapped its third button onto its own row inside a 272px menu
   (measured at 390px) with two fixed tracks. Auto-flow column fits however many options the group
   holds, evenly — kept so the next segmented control added here cannot reintroduce that. */
.tb-seg {
  position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 3px;
  padding: 3px; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--surface-3) 75%, transparent);
  box-shadow: var(--neu-in);
}
/* 36px min-height is the platform touch floor (tokens.css). These were 27px — fine with a mouse,
   under the floor for a thumb, and a segmented control in a dropdown is exactly what someone
   reaches for on a phone. */
.tb-seg-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 36px; padding: 7px 4px; border-radius: var(--r-xs);
  font-size: 12px; font-weight: 500; color: var(--muted);
  transition: color calc(.18s * var(--motion, 1)) ease,
              background calc(.22s * var(--motion, 1)) ease,
              box-shadow calc(.22s * var(--motion, 1)) ease;
}
.tb-seg-btn svg { width: 14px; height: 14px; }
.tb-seg-btn:hover { color: var(--ink); }
/* the selected side is extruded out of the trough, same language as the active nav item */
.tb-seg-btn[aria-checked="true"] {
  color: var(--accent-ink); font-weight: 600; background: var(--surface);
  box-shadow: 0 2px 7px -2px color-mix(in srgb, var(--accent-solid) 32%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 72%, transparent);
}
[data-theme="dark"] .tb-seg-btn[aria-checked="true"] {
  background: color-mix(in srgb, var(--surface-3) 92%, transparent);
  box-shadow: 0 2px 9px -3px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent);
}
.tb-seg-btn:focus-visible { outline: 2px solid var(--accent-solid); outline-offset: 1px; }

.tb-menu-sep { height: 1px; background: var(--rule); margin: 5px 4px; }
.tb-menu-item {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 11px; border-radius: var(--r-sm);
  font-size: 13px; color: var(--ink-2); text-decoration: none;
  transition: background calc(.16s * var(--motion, 1)) ease,
              color calc(.16s * var(--motion, 1)) ease,
              padding-left calc(.22s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1);
}
.tb-menu-item svg { width: 15px; height: 15px; flex-shrink: 0; }
.tb-menu-item:hover { background: var(--accent-soft); color: var(--accent-ink); padding-left: 14px; }
.tb-menu-item.danger { color: var(--danger); }
.tb-menu-item.danger:hover { background: var(--danger-soft); color: var(--danger); }
.tb-menu-item:focus-visible { outline: 2px solid var(--accent-solid); outline-offset: -2px; }

/* ── page-supplied extras (preview actions, admin alerts bell) ─────────────────
   Anything a page drops into the bar still arrives wearing the flat page-body button
   styles from app.css, which read as pasted-on next to the glass. These rules re-dress
   those controls in the bar's own language — pressed-glass surface, top light catch,
   lift + accent bloom on hover — without touching how the same classes look in a page
   body. Scoped to .tb-right so only bar-hosted instances change. */
.tb-divider { width: 1px; height: 20px; flex-shrink: 0; background: var(--rule-2); }

.tb-right .btn,
.tb-right .btn-bell {
  border-radius: var(--r-sm); padding: 8px 15px; font-size: 12.5px; font-weight: 500;
  transition: color calc(.18s * var(--motion, 1)) ease,
              box-shadow calc(.26s * var(--motion, 1)) ease,
              transform calc(.26s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1),
              background calc(.2s * var(--motion, 1)) ease;
}
.tb-right .btn:hover, .tb-right .btn-bell:hover { transform: translateY(-1px); }
.tb-right .btn:active, .tb-right .btn-bell:active { transform: translateY(0); }
.tb-right .btn:focus-visible, .tb-right .btn-bell:focus-visible {
  outline: 2px solid var(--accent-solid); outline-offset: 2px;
}

/* secondary/neutral: seated in the glass, same trough-lit surface as .tb-icon */
.tb-right .btn-outline,
.tb-right .btn-bell {
  background: color-mix(in srgb, var(--surface-3) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--rule) 70%, transparent);
  color: var(--ink-2);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.tb-right .btn-outline:hover,
.tb-right .btn-bell:hover {
  color: var(--accent-ink); background: color-mix(in srgb, var(--surface) 70%, transparent);
  border-color: color-mix(in srgb, var(--accent-solid) 40%, transparent);
  box-shadow: 0 4px 12px -4px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent);
}

/* primary: extruded key, matching the active nav item rather than a flat fill */
.tb-right .btn-primary {
  background: var(--accent-grad); color: #fff; border: 0;
  box-shadow: 0 4px 14px -5px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 42%, transparent);
}
.tb-right .btn-primary:hover {
  filter: none;                                  /* the glow carries it, not a brightness jump */
  box-shadow: 0 8px 22px -6px var(--accent-glow),
              inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
}
.tb-right .btn svg { width: 14px; height: 14px; }

/* the alerts count dot sits on a pill now */
.tb-right .alerts-badge { margin-left: 1px; }

/* deck context chip: reads as an inset label in the glass, not loose text.
   flex-shrink: 0 because it was the item the cluster crushed when space ran short —
   "Telkomsel" came out as "Telko…". It now either shows whole or not at all (below the
   width where it fits, the media query drops it). */
.tb-right .pv-context {
  flex-shrink: 0;
  padding: 5px 13px; border-radius: var(--r-xs);
  background: color-mix(in srgb, var(--surface-3) 45%, transparent);
  border: 1px solid color-mix(in srgb, var(--rule) 60%, transparent);
  box-shadow: inset 1px 1px 3px color-mix(in srgb, var(--ink) 5%, transparent),
              inset -1px -1px 3px color-mix(in srgb, #fff 45%, transparent);
}
[data-theme="dark"] .tb-right .pv-context {
  box-shadow: inset 1px 1px 4px rgba(0, 0, 0, 0.4),
              inset -1px -1px 4px color-mix(in srgb, #fff 3%, transparent);
}
.tb-right .pv-context .pv-type {
  font-family: var(--font-mono); font-size: 9.2px; font-weight: 600; letter-spacing: .1em;
}
/* a genuinely long brand still has to stop somewhere, but the cap is wide enough that
   ordinary names ("Agus Harimurti Yudhoyono") render in full */
.tb-right .pv-context .pv-brand { max-width: 190px; }

/* ── responsive ────────────────────────────────────────────────────────────────
   Narrow viewports drop the labels to icons before anything wraps or clips, then
   the identity text, so the centred rail keeps its centre as long as possible. */
@media (max-width: 1000px) {
  /* the name/role block goes first — the dropdown head still carries both */
  .tb-who { display: none; }
}
@media (max-width: 1040px) {
  /* Profile and Admin leave the rail HERE, not at 760px. Between 761px and 1040px the bar
     used to show five keys with their labels clipped away: nothing named any of them, and
     two of the five went to destinations the avatar menu already lists. Dropping that pair
     buys back the width to keep the labels on the three keys that are actually navigation,
     which is the whole point of a nav bar. Profile and Admin stay reachable in #tb-menu,
     which is present at every width. */
  .tb-link.tb-secondary { display: none; }
  .tb-link { padding: 8px 11px; }
}
@media (max-width: 1360px) {
  /* Below this the right half cannot hold the chip AND both deck actions, and a centred rail
     means the right side only ever gets half the bar. The chip goes rather than shrink: the
     deck name is already in the page heading and the tab title. Measured, not guessed —
     Decks + Download + avatar + gaps need ~265px, the chip ~110px, and the right track is
     (W - 497 rail - padding) / 2. */
  .tb-right .pv-context { display: none; }
}
/* ══════════════════════════════════════════════════════════════════════════════
   PHONES — the rail leaves the bar and becomes a bottom dock
   ─────────────────────────────────────────────────────────────────────────────
   Two things were wrong with a top rail at 390px. Reaching it means crossing the whole
   display with a thumb, and five icon-only keys plus the brand plus the account trigger
   left the rail sideways-scrolling with its labels clipped away — so the primary
   navigation was both the hardest thing to reach and the least legible.

   Below 760px, therefore:
     · the bar keeps the brand and ONE trigger (the hamburger),
     · Profile and Admin leave the rail for that hamburger, which already listed both,
     · the three that remain become a centred dock at the bottom, with icon AND label.
   Three keys instead of five is what buys the width for the labels and the height for
   the touch target; the split is the whole point rather than a side effect.
   ══════════════════════════════════════════════════════════════════════════════ */
@media (max-width: 760px) {
  /* One number, read by both the dock and the scroll-clearance rules below. 64px is the rail's
     MEASURED height (52px key + 2x5px trough padding + 2x1px border), not a guess — the
     clearances are derived from it, and a nominal 62 left the query composer flush against the
     dock's top edge with a 0px gap. */
  :root { --tb-dock-h: 64px; }

  /* .tb-mid is position: fixed below, so it leaves the grid entirely. TWO tracks, not
     three: with three declared, .tb-right would be auto-placed into the empty middle one
     and the account trigger would land in the centre of the bar. */
  .topbar { grid-template-columns: minmax(0, 1fr) auto; gap: 10px; padding: 9px 14px; }

  /* ⚠ THE reason the dock needs this: backdrop-filter on an ancestor makes that ancestor the
     containing block for position: fixed descendants. With the blur on .topbar itself, the
     dock's `bottom: 0` resolved against the BAR and it rendered at the top of the screen
     (measured: top -16, bottom 58). Same glass, painted by a pseudo-element instead, so
     .topbar carries no filter and `fixed` means the viewport again. */
  .topbar { background: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .topbar::before {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    /* 86% rather than --glass: without backdrop-filter support this face is the only thing
       between bar text and page content, and at 86% it stays legible on its own */
    background: color-mix(in srgb, var(--surface) 86%, transparent);
    -webkit-backdrop-filter: blur(26px) saturate(1.7);
            backdrop-filter: blur(26px) saturate(1.7);
  }
  /* the wordmark comes BACK — it was only hidden to make room for the rail, and the rail
     is no longer up here */
  .tb-word { display: inline-flex; }

  /* ── the dock ── */
  .tb-mid {
    position: fixed; z-index: 95; left: 0; right: 0; bottom: 0;
    justify-content: center; align-items: flex-end;
    padding: 0 14px calc(10px + env(safe-area-inset-bottom, 0px));
    /* the full-width band is a positioner only. With pointer events it would swallow every
       tap along the bottom of the page — the query composer's send button sits right there. */
    pointer-events: none;
  }
  .tb-nav {
    pointer-events: auto;
    width: 100%; max-width: 400px;
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 4px;
    padding: 5px; border-radius: var(--r-lg);
    /* it FLOATS over page content now rather than sitting inside a bar, so the face is more
       opaque and it casts downward. Same reading as before — a trough holding raised keys —
       with the elevation a floating control needs. */
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    -webkit-backdrop-filter: blur(22px) saturate(1.7);
            backdrop-filter: blur(22px) saturate(1.7);
    box-shadow: var(--neu-in),
                0 16px 38px -14px color-mix(in srgb, var(--ink) 42%, transparent);
  }
  /* the cursor spotlight is a mouse affordance and there is no cursor here */
  .tb-nav::before { display: none; }

  /* ── keys: icon over label, sized to be hit without aiming ── */
  .tb-link {
    flex-direction: column; justify-content: center; gap: 4px;
    padding: 8px 4px 7px; min-height: 52px;
    border-radius: var(--r-sm); font-size: 11px; letter-spacing: -.004em;
  }
  .tb-link svg { width: 21px; height: 21px; }
  /* the dock stacks icon over label, so the label needs its own line box */
  .tb-link span { white-space: nowrap; line-height: 1.1; }
  /* a hover lift on touch leaves the key hanging raised after the finger goes */
  .tb-link:hover { transform: none; }
  /* Profile and Admin are in the hamburger now */
  .tb-link.tb-secondary { display: none; }

  /* ── one trigger, not two ── */
  .tb-avatar { display: none; }
  .tb-burger { display: grid; }
  .tb-menu-ava { display: grid; }
  .tb-menu { width: min(272px, calc(100vw - 28px)); }
}

/* ── dock clearance: nothing may come to rest underneath it ────────────────────
   The dock is fixed, so each page scroller has to reserve the room or its last row ends
   up behind it — the query composer, the report form's submit, the final table row. The
   compensation lives here, next to the thing that causes it and reading the same
   --tb-dock-h. Each selector is one class deeper than the page's own rule on purpose:
   app.css/query.css/superadmin_base.html all set `padding` on these shells and all load
   AFTER this file, so an equal-specificity padding-bottom here would simply lose. */
@media (max-width: 760px) {
  /* + the dock's own 10px lift off the bottom edge + a real gap, so content stops ABOVE the
     dock rather than tucking under its glass. The query wrap needs less because the composer
     carries 22px of its own bottom padding inside the band. */
  .app > .main          { padding-bottom: calc(var(--tb-dock-h) + 24px); }
  .app > .q-main-wrap   { padding-bottom: calc(var(--tb-dock-h) + 16px); }
  body > .preview-shell { padding-bottom: calc(var(--tb-dock-h) + 16px); }

  /* The admin screens are a different animal: `.page` is a 100vh flex shell and every box
     inside it is overflow: hidden, so NOTHING scrolls (measured — zero scrollable elements on
     /superadmin) and the dock simply sat over the bottom 74px of the table with no way to move
     it. Padding on the shell is the fix rather than on a scroller: with border-box the 100vh
     height absorbs it, so every child reflows above the dock and the inner list scrolls if it
     needs to. `body >` because superadmin_base.html styles `.page` in its own <style>, which
     loads after this file and would otherwise win at equal specificity. */
  body > .page { padding-bottom: calc(var(--tb-dock-h) + 14px); }
}

