/* ==========================================================================
   LIQUID NAV — presentation only.

   Every dimension is derived from `--nav-scale`, which carries the overlay's
   fullscreen magnification, so the bar grows with the rest of the UI without
   any size being written down twice. `--nav-r`, `--bead-d` and `--rise` are
   written by ViewerToolbar.tsx from the measured box: the path and the CSS have to
   agree about where the bead sits, and the geometry is the one place that
   knows.
   ========================================================================== */

.vf-nav {
  --nav-scale: 1;
  --nav-h: calc(64px * var(--nav-scale));
  /* A floor, not a fixed width: slots grow to their label. Russian needs it —
     "Без потолка" is half again as wide as "No ceiling". */
  --nav-slot: calc(62px * var(--nav-scale));
  --nav-gap: calc(28px * var(--nav-scale));
  --nav-icon: calc(19px * var(--nav-scale));

  /* Written by measure(); these are only a sane first paint. */
  --nav-r: 18px;
  --bead-d: 37px;
  --icon-y: 27px;
  --rise: 27px;

  position: relative;
  height: var(--nav-h);
  margin-bottom: calc(20px * var(--nav-scale));
  align-self: center;
  pointer-events: auto;
  /* The bead rides ON the surface, so its top half is outside the box. */
  overflow: visible;
  z-index: 40;
}

.vf-nav__skin {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  /* The shadow belongs to the liquid shape, not to a rectangle behind it. */
  filter: drop-shadow(0 14px 30px rgb(0 0 0 / 0.28));
}

.vf-nav__fill {
  fill: var(--vf-panel);
  stroke: var(--vf-border);
  stroke-width: 1;
}

/* --- the bead ------------------------------------------------------------ */

.vf-nav__bead {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--bead-d);
  height: var(--bead-d);
  /* Centre it on (x, top edge): the bowl in the path is centred there too. */
  margin: calc(var(--bead-d) / -2) 0 0 calc(var(--bead-d) / -2);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background:
    linear-gradient(
      168deg,
      color-mix(in srgb, var(--vf-action) 74%, #fff),
      var(--vf-action) 62%
    );
  box-shadow:
    0 2px 6px color-mix(in srgb, var(--vf-action) 45%, transparent),
    0 8px 20px rgb(0 0 0 / 0.22),
    inset 0 1px 1px rgb(255 255 255 / 0.35);
  will-change: transform;
}

/* --- items --------------------------------------------------------------- */

.vf-nav__groups {
  position: relative;
  display: flex;
  align-items: stretch;
  height: 100%;
  /*
    NOTHING in this bar may be a scroll container. `overflow-x: auto` was tried
    here to keep a narrow bar out of the corners, and it clipped the icons:
    CSS gives no way to scroll one axis while leaving the other visible — set
    either and `visible` on the other computes to `auto` — and the selected
    icon deliberately rises above the bar's top edge into the bead.

    The padding below is not cosmetic either. `measure()` shrinks the bead
    until its outer shoulder
    clears the bar's own corner arc, so the distance from the first slot centre
    to the left edge is a hard floor on bead size: at 10px of padding the bead
    collapsed to its 22px minimum. A socket half-width is ~32px at the intended
    37px bead, and the corner takes ~18px, so the first slot centre has to sit
    about 54px in — which is this padding plus half a slot.
  */
  padding-left: calc(32px * var(--nav-scale));
  /*
    The right side needs no such clearance — the last bead-carrying slot is the
    ceiling toggle, two slots in — and matching the left made the trailing
    group look adrift in empty bar.
  */
  padding-right: calc(18px * var(--nav-scale));
  /*
    Group gaps are not decoration. A socket is about 69px wide at the 41px bead
    this slot width yields, so beads in neighbouring groups would fuse into one
    dent without it. The gap is what keeps every pair of live beads far enough
    apart for their shoulders to clear.
  */
  gap: var(--nav-gap);
}

.vf-nav__group {
  position: relative;
  display: flex;
  align-items: stretch;
}

/*
  The rule that says these are separate kinds of control. The gap alone reads
  as spacing, not as grouping — which matters more here than on the old bar,
  because each group is also a separate bead. It is short and vertically
  centred so it stays clear of the dent in the top edge: a socket reaches
  about 8px past a slot into the gap, while the rule sits 14px in and starts
  well below the surface.
*/
.vf-nav__group + .vf-nav__group::before {
  content: '';
  position: absolute;
  left: calc(var(--nav-gap) / -2);
  top: 50%;
  width: 1px;
  height: calc(22px * var(--nav-scale));
  transform: translate(-50%, -50%);
  background: var(--vf-border);
  pointer-events: none;
}

.vf-nav__item {
  /* 0 at rest, 1 when this slot's bead is seated on it. Written by paint(). */
  --t: 0;

  position: relative;
  /*
    The label sits in normal flow so that it sizes the slot; the icon is the
    absolutely positioned one, because it has to travel out of the button and
    into the bead. Doing it the other way round is why Russian labels were
    truncated: an absolutely positioned label cannot widen its parent.
  */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-width: var(--nav-slot);
  height: 100%;
  padding: 0 calc(9px * var(--nav-scale)) calc(9px * var(--nav-scale));
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  font: inherit;
  -webkit-tap-highlight-color: transparent;
}

.vf-nav__item:disabled {
  cursor: default;
  opacity: 0.4;
}

/* Labels are permanent, so hover cannot be "the name appears". It lifts the
   inactive ink to full strength instead — visible, and impossible to mistake
   for the pressed state, which is carried by the bead. */
@media (hover: hover) {
  .vf-nav__item:hover:not(:disabled) .vf-nav__icon,
  .vf-nav__item:hover:not(:disabled) .vf-nav__label {
    color: var(--vf-text);
  }
}

.vf-nav__item:focus-visible .vf-nav__icon,
.vf-nav__item:focus-visible .vf-nav__label {
  color: var(--vf-text);
}

.vf-nav__item:focus-visible {
  outline: 2px solid var(--vf-focus);
  outline-offset: -3px;
  border-radius: calc(12px * var(--nav-scale));
}

.vf-nav__icon {
  position: absolute;
  left: 50%;
  top: var(--icon-y);
  width: var(--nav-icon);
  height: var(--nav-icon);
  /* Lifted by the bead, never by hover: the rise is what selection means. */
  transform: translate(-50%, -50%) translateY(calc(var(--t) * var(--rise) * -1));
  color: color-mix(
    in oklab,
    var(--vf-text-muted) calc((1 - var(--t)) * 100%),
    var(--vf-on-action)
  );
  transition: color 180ms cubic-bezier(.16, 1, .3, 1);
}

.vf-nav__label {
  /*
    In flow, so the slot is as wide as the word — and it does not move. It used
    to rise as its bead arrived, which meant the one part of the bar carrying
    the words shifted under the reader every time a mode changed. Selection is
    said twice instead, without displacement: the ink comes up to full strength
    and a rule draws itself underneath.
  */
  position: relative;
  white-space: nowrap;
  font-size: calc(11px * var(--nav-scale));
  font-weight: 600;
  letter-spacing: .01em;
  pointer-events: none;
  /*
    Always readable. Revealing a name only on hover or selection turns the rest
    of the bar into a row of unlabelled glyphs, and one of these controls —
    Reset — has no active state to reveal it at all. Selection is carried by
    the bead, the raised icon and the ink weight below instead of by presence.
  */
  opacity: 1;
  color: color-mix(
    in oklab,
    var(--vf-text-muted) calc((1 - var(--t)) * 100%),
    var(--vf-text)
  );
  transition: color 180ms cubic-bezier(.16, 1, .3, 1);
}

/* A stateful label may change text without changing the slot width. Both
   strings occupy the same grid cell; the hidden one contributes only size. */
.vf-nav__label-frame {
  display: grid;
  place-items: end center;
}

.vf-nav__label-frame > * {
  grid-area: 1 / 1;
}

.vf-nav__label--width {
  visibility: hidden;
}

.vf-nav__label--width::after {
  display: none;
}

/* The underline follows the liquid bead's existing spring without adding a
   second animation. Labels stay still while selection remains visible. */
.vf-nav__label::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-3px * var(--nav-scale));
  height: calc(1.5px * var(--nav-scale));
  border-radius: 999px;
  background: currentColor;
  transform: scaleX(var(--t));
  transform-origin: center;
  pointer-events: none;
}

/* --- Liquid Glass --------------------------------------------------------
   The effect uses five stacked layers: frost, SDF refraction, tint, pointer
   sheen and a lit rim.
   The React control model stays ours, including multiple independent active
   groups and stable label widths. */

.vf-nav__glass-defs,
.vf-nav__glass-layer {
  display: none;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav {
  --vf-lg-ink: #111722;
  --vf-lg-ink-soft: #374154;
  --vf-lg-tint: rgb(238 243 250 / 0.78);
  --vf-lg-saturation: 180%;
  --vf-lg-blur: 7px;
  --vf-lg-rim-high: rgb(255 255 255 / 0.95);
  --vf-lg-rim-low: rgb(255 255 255 / 0.16);
  --vf-lg-rim-shade: rgb(24 28 44 / 0.10);
  --vf-lg-sheen: rgb(255 255 255 / 0.55);
  --vf-lg-active-a: rgb(255 255 255 / 0.88);
  --vf-lg-active-b: rgb(102 137 199 / 0.34);
  --vf-lg-active-shadow:
    0 1px 2px rgb(24 28 44 / 0.10),
    0 6px 14px -8px rgb(24 28 44 / 0.30);

  height: calc(68px * var(--nav-scale));
  border-radius: 999px;
  isolation: isolate;
  box-shadow:
    0 1px 1px rgb(24 28 44 / 0.04),
    0 6px 14px -6px rgb(24 28 44 / 0.16),
    0 26px 46px -18px rgb(24 28 44 / 0.34);
}

.vf-viewer[data-theme="dark"][data-toolbar-style="liquid_glass"] .vf-nav {
  --vf-lg-ink: #f6f8fc;
  --vf-lg-ink-soft: #c6cfde;
  --vf-lg-tint: rgb(15 21 32 / 0.76);
  --vf-lg-saturation: 150%;
  --vf-lg-blur: 8px;
  --vf-lg-rim-high: rgb(255 255 255 / 0.34);
  --vf-lg-rim-low: rgb(255 255 255 / 0.10);
  --vf-lg-rim-shade: rgb(0 0 0 / 0.34);
  --vf-lg-sheen: rgb(190 214 255 / 0.20);
  --vf-lg-active-a: rgb(188 211 255 / 0.28);
  --vf-lg-active-b: rgb(126 157 215 / 0.18);
  --vf-lg-active-shadow:
    0 1px 2px rgb(0 0 0 / 0.30),
    0 8px 18px -10px rgb(0 0 0 / 0.70);
  box-shadow:
    0 1px 1px rgb(0 0 0 / 0.30),
    0 8px 18px -8px rgb(0 0 0 / 0.55),
    0 30px 60px -22px rgb(0 0 0 / 0.70);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__skin,
.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__bead {
  display: none;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-defs {
  display: block;
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-layer {
  display: block;
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-base {
  backdrop-filter: blur(var(--vf-lg-blur)) saturate(var(--vf-lg-saturation)) brightness(1.02);
  -webkit-backdrop-filter: blur(var(--vf-lg-blur)) saturate(var(--vf-lg-saturation)) brightness(1.02);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-warp {
  backdrop-filter: var(--vf-liquid-glass-filter, none);
  -webkit-backdrop-filter: var(--vf-liquid-glass-filter, none);
}

/*
  The tint is the bar's density floor, not a decorative ramp.

  It used to fade to 55% of its own alpha across the bar. That put the thinnest
  glass exactly where the content is: icons sit at ~40% of the bar's height and
  labels at ~67%, so the ramp bottomed out under the text rather than in empty
  space. Measured against a white scene, the dark bar's inactive label fell to
  2.43:1; against a black scene the light bar's fell to 2.75:1. Both themes only
  cleared 4.5:1 while the scene behind stayed inside a 135-170 band of
  brightness — which a sky, a white wall or dark furniture leaves immediately.

  Both inks need roughly 0.72 alpha behind them in the worst case, and there is
  no stretch of this bar without content to spend a dip on. So the ramp is now
  shallow enough to never cross that floor: 94% at the far end holds ~0.73 at
  the label band. The glass reads as glass through the blur, the refraction
  warp, the sheen and the rim — none of which the readability depends on.
*/
.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-tint {
  background: linear-gradient(
    160deg,
    var(--vf-lg-tint),
    color-mix(in srgb, var(--vf-lg-tint) 94%, transparent)
  );
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-sheen {
  background: radial-gradient(
    calc(180px * var(--nav-scale)) calc(120px * var(--nav-scale))
      at var(--vf-lg-pointer-x, 50%) var(--vf-lg-pointer-y, 0%),
    var(--vf-lg-sheen),
    transparent 68%
  );
  opacity: 0;
  transition: opacity 180ms cubic-bezier(.16, 1, .3, 1);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav:hover .vf-nav__glass-sheen,
.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav:focus-within .vf-nav__glass-sheen {
  opacity: 1;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-rim {
  padding: 1px;
  background: linear-gradient(
    150deg,
    var(--vf-lg-rim-high) 0%,
    var(--vf-lg-rim-low) 34%,
    var(--vf-lg-rim-shade) 62%,
    var(--vf-lg-rim-high) 100%
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__groups {
  z-index: 1;
  align-items: center;
  padding: calc(7px * var(--nav-scale));
  gap: calc(20px * var(--nav-scale));
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__group {
  align-items: stretch;
  height: 100%;
  gap: calc(2px * var(--nav-scale));
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__group + .vf-nav__group::before {
  left: calc(-10px * var(--nav-scale));
  height: calc(28px * var(--nav-scale));
  background: linear-gradient(
    transparent,
    color-mix(in srgb, var(--vf-lg-ink) 34%, transparent) 26%,
    color-mix(in srgb, var(--vf-lg-ink) 34%, transparent) 74%,
    transparent
  );
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item {
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: calc(4px * var(--nav-scale));
  min-width: var(--nav-slot);
  height: 100%;
  padding: calc(7px * var(--nav-scale)) calc(10px * var(--nav-scale));
  border-radius: 999px;
  color: var(--vf-lg-ink-soft);
  transition:
    color 180ms cubic-bezier(.16, 1, .3, 1),
    background-color 180ms cubic-bezier(.16, 1, .3, 1),
    box-shadow 180ms cubic-bezier(.16, 1, .3, 1),
    transform 120ms cubic-bezier(.16, 1, .3, 1);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item:active:not(:disabled) {
  transform: scale(0.965);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item[aria-pressed="true"] {
  color: var(--vf-lg-ink);
  background: linear-gradient(180deg, var(--vf-lg-active-a), var(--vf-lg-active-b));
  box-shadow:
    var(--vf-lg-active-shadow),
    inset 0 1px 0 rgb(255 255 255 / 0.72);
  backdrop-filter: blur(3px) saturate(120%);
  -webkit-backdrop-filter: blur(3px) saturate(120%);
}

.vf-viewer[data-theme="dark"][data-toolbar-style="liquid_glass"] .vf-nav__item[aria-pressed="true"] {
  box-shadow:
    var(--vf-lg-active-shadow),
    inset 0 1px 0 rgb(255 255 255 / 0.20);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__icon {
  position: static;
  flex: 0 0 auto;
  transform: none;
  color: currentColor;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__label {
  color: currentColor;
  transform: none;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__label::after {
  display: none;
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item:hover:not(:disabled) .vf-nav__icon,
.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item:hover:not(:disabled) .vf-nav__label,
.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item:focus-visible .vf-nav__icon,
.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item:focus-visible .vf-nav__label {
  color: var(--vf-lg-ink);
}

.vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__item:focus-visible {
  outline-color: var(--vf-lg-ink);
  outline-offset: -4px;
  border-radius: 999px;
}

/* Conventional button skin for customers whose host UI is geometric. The
   React control model stays the same; only the project-published skin changes. */
.vf-viewer[data-toolbar-style="buttons"] .vf-nav {
  height: calc(64px * var(--nav-scale));
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__skin,
.vf-viewer[data-toolbar-style="buttons"] .vf-nav__bead,
.vf-viewer[data-toolbar-style="buttons"] .vf-nav__group + .vf-nav__group::before {
  display: none;
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__groups {
  padding: 0;
  gap: calc(10px * var(--nav-scale));
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__group {
  gap: calc(8px * var(--nav-scale));
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__item {
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: calc(4px * var(--nav-scale));
  min-width: var(--nav-slot);
  padding: calc(7px * var(--nav-scale)) calc(10px * var(--nav-scale));
  border: 1px solid var(--vf-border);
  border-radius: var(--vf-control-radius, 10px);
  background: var(--vf-panel);
  box-shadow: 0 8px 22px rgb(0 0 0 / 0.18);
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__item[aria-pressed="true"] {
  border-color: var(--vf-action);
  background: var(--vf-action);
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__icon {
  position: static;
  transform: none;
  flex: 0 0 auto;
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__label {
  transform: none;
}

/* A filled conventional button already carries selection; the liquid
   underline belongs only to the liquid skin. */
.vf-viewer[data-toolbar-style="buttons"] .vf-nav__label::after {
  display: none;
}

.vf-viewer[data-toolbar-style="buttons"] .vf-nav__item[aria-pressed="true"] .vf-nav__icon,
.vf-viewer[data-toolbar-style="buttons"] .vf-nav__item[aria-pressed="true"] .vf-nav__label {
  color: var(--vf-on-action);
}

@media (max-width: 720px) {
  .vf-nav {
    --nav-h: calc(58px * var(--nav-scale));
    --nav-slot: calc(44px * var(--nav-scale));
    --nav-gap: calc(20px * var(--nav-scale));
    margin-bottom: calc(12px * var(--nav-scale));
    /*
      No max-width and no scrolling here either — see above. Below this width
      the bar simply outgrows the viewport, which is one of the open items in
      the mobile pass rather than something to hide behind a clipped overflow.
    */
  }
}

@media (prefers-reduced-motion: reduce) {
  .vf-nav__icon,
  .vf-nav__label,
  .vf-nav__item,
  .vf-nav__glass-sheen {
    transition: none;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-base,
  .vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-warp,
  .vf-viewer[data-toolbar-style="liquid_glass"] .vf-nav__glass-sheen {
    display: none;
  }

  .vf-viewer[data-theme="light"][data-toolbar-style="liquid_glass"] .vf-nav__glass-tint {
    background: #f3f4f7;
  }

  .vf-viewer[data-theme="dark"][data-toolbar-style="liquid_glass"] .vf-nav__glass-tint {
    background: #11131a;
  }
}
