/* ═══════════════════════════════════════════════════════════════════════
   Bingqilin shared chrome — the app shell: fonts, cross-document view
   transitions, the top app bar and the bottom navigation bar.

   Load order on every page:  tokens.css → chrome.css → ui.css
   Colour, type, shape, motion and stacking all come from tokens.css;
   general components (buttons, cards, fields, dialogs…) from ui.css.
   Only the shell itself lives here.
   ═══════════════════════════════════════════════════════════════════════ */

/* Vendored (not the Google Fonts CDN) — Google Sans Flex is the site's
   only font, used for body and display text alike; Material Icons is the
   icon font behind every .material-icons span. The files live in
   shared/fonts/; the paths below are relative to this stylesheet, so they
   resolve the same whichever page depth includes it.

   Google Sans Flex is one variable file, cut from the Google Fonts API
   with Roundness pinned at 100 (the rounded Google Sans) and optical size
   pinned at its default of 18, which has the same metrics — x-height, cap
   height, advances, line box — as the static Google Sans it replaced, so
   nothing reflows. Weight stays live across 400–700, which covers every
   weight the site sets (400, 500, 600). Latin subset, like the old files. */
@font-face { font-family: 'Google Sans Flex'; font-style: normal; font-weight: 400 700; font-display: swap; src: url('fonts/GoogleSansFlex-Rounded.woff2') format('woff2'); }
/* font-display: block, not swap — a ligature font that swaps in shows the
   literal glyph names ("video_library") first. */
@font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; font-display: block; src: url('fonts/MaterialIcons-Regular.woff2') format('woff2'); }

/* ui.css owns .material-icons layout (size, alignment). This is the one
   place that binds the glyph font and turns ligatures on. */
.material-icons {
  font-family: 'Material Icons';
  font-weight: normal;
  font-style: normal;
  direction: ltr;
  -webkit-font-feature-settings: 'liga';
  font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
}

/* ── Cross-document view transitions ───────────────────────────────────
   Media/Live/Tools and each tool are separate documents, so moving
   between them is a full navigation — without this it is a hard flash to
   white. Naming .top-bar and .bottom-dock morphs that shared chrome
   across the navigation instead of crossfading two whole-page snapshots,
   so the shell reads as staying put while only the content changes.
   Inert (ignored, normal navigation) where it is unsupported. */
@view-transition { navigation: auto; }
.top-bar { view-transition-name: top-bar; }
.bottom-dock { view-transition-name: bottom-dock; }

/* ── Top app bar (M3 small) ────────────────────────────────────────── */
.top-bar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: calc(var(--topbar-h) + env(safe-area-inset-top));
  padding:
    env(safe-area-inset-top)
    calc(0.35rem + env(safe-area-inset-right))
    0
    calc(0.35rem + env(safe-area-inset-left));
  /* Solid, not a translucent blur — content scrolling underneath used to
     ghost through the bar. */
  background: var(--md-surface-container);
  border-bottom: 1px solid var(--border);
}
.top-bar__lead { display: flex; align-items: center; gap: 0.15rem; min-width: 0; }
/* Not interactive — the app's wordmark, the same on every page. */
.top-bar__brand { display: flex; align-items: baseline; gap: 0.45rem; padding-left: 0.5rem; user-select: none; }
.top-bar__name {
  font: var(--type-title-large);
  letter-spacing: var(--track-title-large);
  color: var(--primary-dark);
}
/* When a sub-page shows a back button, the wordmark sits right against it
   and does not need its own leading inset. */
.top-bar__lead .icon-btn + .top-bar__brand { padding-left: 0; }
.top-bar__actions { display: flex; align-items: center; gap: 0.1rem; }
/* The bar is 56px; a 48dp icon button fits with 4px either side. */
.top-bar .icon-btn { width: 44px; height: 44px; }
.top-bar .icon-btn::before { width: 40px; height: 40px; }

/* ── Ripple ────────────────────────────────────────────────────────────
   Material's touch feedback. The state layers in ui.css cover hover,
   focus and press for a pointer; a touch has no hover, so without this
   there is no acknowledgement of a tap at all — the single biggest reason
   a page feels like a document instead of an app. chrome.js
   (BQChrome.initRipple) appends and removes the .ripple span; each page
   passes its own selector list for which elements get one. */
.ripple {
  position: absolute;
  z-index: 1;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.20;
  transform: scale(0);
  pointer-events: none;
  animation: ripple-anim 0.55s var(--ease-emphasized) forwards;
}
@keyframes ripple-anim { to { transform: scale(1); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .ripple { display: none; } }

/* ── Bottom navigation (M3 NavigationBar) ──────────────────────────────
   Media / Live / Tools, present on every page. Wrapped in .bottom-dock
   (which carries the view-transition-name above, and on live.html also
   holds the mini player) so navigating morphs the bar instead of flashing
   it. Hidden with transform + opacity rather than display:none on pages
   that push a full-screen sub-view over it: a box collapsing to zero
   height is itself what a View Transition would animate, which captures
   as a squash rather than a slide. Staying position:fixed throughout
   means the hidden state costs nothing in layout, and pages that never
   toggle .bottom-dock--hidden simply never trigger it. */
.bottom-dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-dock);
  display: flex;
  flex-direction: column;
  transition: transform var(--t), opacity var(--t);
}
.bottom-dock--hidden { transform: translateY(100%); opacity: 0; pointer-events: none; }
/* The nav stays up on every view; fullscreen is the one thing that takes
   it away. A fullscreened element already paints over it, so this is for
   the browsers that let the page underneath show through at the edges. */
:root:has(:fullscreen) .bottom-dock { visibility: hidden; }

.bottom-nav {
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  min-height: var(--bottomnav-h);
  padding:
    0.25rem
    calc(0.5rem + env(safe-area-inset-right))
    calc(0.25rem + env(safe-area-inset-bottom))
    calc(0.5rem + env(safe-area-inset-left));
  background: var(--md-surface-container);
  border-top: 1px solid var(--border);
}
.bottom-nav__item {
  position: relative;
  overflow: hidden;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-muted);
  text-decoration: none;
  cursor: pointer;
  -webkit-touch-callout: none;
  user-select: none;
  transition: color var(--t);
}
.bottom-nav__item:focus-visible { outline: 2px solid var(--md-primary); outline-offset: -2px; border-radius: var(--shape-m); }

/* M3's active indicator: a 32dp-tall pill behind the icon only. */
.bottom-nav__icon-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 28px;
  border-radius: var(--shape-l);
  transition: background var(--t), color var(--t);
}
.bottom-nav__icon-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t);
}
@media (hover: hover) {
  .bottom-nav__item:hover { color: var(--text); }
  .bottom-nav__item:hover .bottom-nav__icon-wrap::before { opacity: var(--state-hover); }
}
.bottom-nav__item:active .bottom-nav__icon-wrap::before { opacity: var(--state-press); }
.bottom-nav__icon-wrap .material-icons { font-size: 22px; }

.bottom-nav__label {
  font: var(--type-label-medium);
  font-size: 0.68rem;
  letter-spacing: 0.01em;
}

.bottom-nav__item--active,
.bottom-nav__item[aria-current="page"] { color: var(--text); }
.bottom-nav__item--active .bottom-nav__icon-wrap,
.bottom-nav__item[aria-current="page"] .bottom-nav__icon-wrap {
  background: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}
.bottom-nav__item--active .bottom-nav__label,
.bottom-nav__item[aria-current="page"] .bottom-nav__label { font-weight: 600; }



