/* ============================================================
   nx-tabbar.css
   THE ONE FLOATING TAB BAR, its looks. nx-tabbar.js is its markup
   and its behaviour; this file is everything it is painted with.

   WHY THIS FILE EXISTS. The markup was consolidated into
   nx-tabbar.js and the CSS was not, so the same rules were written
   out twice: inline in companion.html for home, and copied into
   appts-shell.css for everything else. Two definitions of one thing
   is the defect this project keeps re-learning; the copies had not
   drifted yet, and the point is that they could not be relied on not
   to. A shared component with per-page styles is half a component.

   So: loaded by every page that renders the bar, and by nothing
   else. Removed from companion.html and from appts-shell.css.

   It expects the host page's design tokens to exist (--glass,
   --hair-2, --ink-3, --secondary and friends). Every page carrying
   the bar loads appts-shell.css or companion.html's own token block,
   both of which define them, so the bar inherits the page's theme
   rather than pinning its own.
   ============================================================ */

/* ============ FLOATING TAB BAR (from O) ============ */
.tabbar{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:56;display:flex;
  align-items:center;gap:2px;padding:7px;border-radius:26px;background:var(--glass);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);border:1px solid var(--hair-2);
  box-shadow:var(--shadow-lg),inset 0 1px 0 var(--glass-hi);
  transition:transform .45s var(--spring),opacity .3s var(--ease),
             width .5s var(--spring),max-width .5s var(--spring)}
body.sheet-open .tabbar{transform:translateX(-50%) translateY(150%);opacity:0}
/* the rail is a full-height surface, so the bar gets out of its way entirely */
body.rail-open .tabbar{transform:translateX(-50%) translateY(150%);opacity:0}
/* Rivo expands out of its own dock and leaves the bar where it is, so the
   only thing to undo here is any translate a sibling state applied. */
body.rivo-open .tabbar{transform:translateX(-50%)}

.tab{position:relative;display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:8px 20px;border-radius:19px;color:var(--ink-3);min-width:74px;
  transition:color .24s var(--ease),background .24s var(--ease),transform .2s var(--bounce)}
.tab span{font-size:10px;font-weight:700;letter-spacing:.02em}
.tab:hover{color:var(--ink-2)}
.tab:active{transform:scale(.92)}
.tab[aria-current="page"]{color:var(--secondary-soft);background:var(--raise-2)}
html[data-theme="light"] .tab[aria-current="page"]{color:var(--secondary)}
.tab .badge{position:absolute;top:6px;right:15px;width:7px;height:7px;border-radius:50%;
  background:var(--secondary);box-shadow:0 0 0 2px var(--glass)}

/* ---- "More" OPENS A ROW ABOVE THE BAR. It used to widen the bar in place,
        and that broke the one control it depends on.

        The bar is centred with translateX(-50%), so ANY change to its width
        moves every tab in it. The More button is the last child, so opening
        it threw the button about 260px to the right, out from under the
        finger that had just pressed it. Pressing again hit whichever
        destination had slid into that spot: the bar would not close, and on a
        phone (where the extras take a second row and push the first row up)
        the first press appeared to do nothing at all and the second one
        opened it. Measured, not guessed: document.elementFromPoint at the
        press position after opening returns A.tab, not the button.

        There is no arrangement that fixes this while the bar changes width,
        because on a centred element the only point that does not move is the
        centre. So the bar no longer changes size. The extra destinations open
        as their own row directly above it, the primary row and the More
        button never move by a pixel, and pressing Less closes what pressing
        More opened. ---- */
.tabbar .tab[data-more]{order:2}
/* NEARLY OPAQUE, AND NOT var(--glass), IN EITHER THEME.
   The bar can afford to be glass: it sits at the foot of the page, it is
   always there, and what shows through it is usually the page's own quiet
   end. This row is different. It opens ON DEMAND, over whatever the page
   happens to be showing, and on the home and arriving pages that is a
   photograph. At --glass (.62 in dark) the foliage read straight through
   eight destination labels.

   The light theme already knew this: it has overridden this rule to .94
   since it was written. Dark never got the same treatment and simply
   inherited the bar's glass, which is the whole defect. The value below is
   the dark counterpart of that .94, and both are written here rather than
   as a token because this rule pair is the only place either is wanted.

   The border and the inset highlight come from the bar for the same reason:
   a panel floating over a photograph needs its own edge, and --hair alone
   disappears against a light patch of one. */
.tab-more{position:absolute;left:50%;bottom:calc(100% + 8px);transform:translateX(-50%) translateY(8px);
  display:flex;align-items:center;gap:2px;padding:6px;border-radius:22px;
  background:rgba(20,27,43,.95);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  border:1px solid var(--hair-2);box-shadow:var(--shadow-lg),inset 0 1px 0 var(--glass-hi);
  opacity:0;
  /* HIDDEN, not merely transparent: a link nobody can see is still in the tab
     order, and a focus ring on it is a WCAG 2.2 failure. The visibility flip
     waits for the close to finish so it does not cut it. */
  visibility:hidden;pointer-events:none;
  transition:opacity .26s var(--ease),transform .42s var(--spring),
             visibility 0s linear .42s}
html[data-theme="light"] .tab-more{background:rgba(255,255,255,.94);
  border-color:rgba(31,42,68,.12)}
.tabbar.wide .tab-more{opacity:1;visibility:visible;pointer-events:auto;
  transform:translateX(-50%);transition-delay:0s}
.tabbar.wide .tab[data-more] .lbl{opacity:.6}
.tab-more .tab{min-width:66px}
@media (prefers-reduced-motion: reduce){
  .tab-more{transition:opacity .001ms,visibility 0s}
}

/* ---- WHAT GIVES WAY TO THE GROWN BAR.
        The bar grows from the centre outwards, so at narrower widths it
        reaches the two bottom corners other floating widgets are docked in.
        They cannot share the corner, so the one that was not asked for
        stands down until More is closed again. nx-tabbar.js sets the class
        on the body precisely so this can be written once, here. ---- */
/* bottom left: the needle exchange and naloxone "hail" widget. It only ever
   had to move because the bar grew into its corner; it does not any more, but
   the row that opens above the bar still sits over the middle of the screen,
   so the two floating controls stay put and only the row is new. */
body.tabbar-wide .nx-hail{transform:none;opacity:1;pointer-events:auto}
/* Bottom right: Ask Rivo used to be pushed off screen below 1360px, because
   the grown bar reached its corner and landed on the Less control, which is
   the one control that gets somebody back out of the state. The bar does not
   grow now, so nothing collides and nothing has to be hidden. */

@media(max-width:860px){
  .tabbar{bottom:12px;width:calc(100% - 24px);justify-content:space-between;padding:6px}
  .tab{padding:7px 4px;min-width:0;flex:1}
  /* A PHONE GETS A SECOND ROW, not a squeeze and not a sideways scroll.
     Eleven tabs across 366px is 32px each: under the 44px target, labels
     overlapping their neighbours, and the More control clipped to a slither
     against the edge. So the four primary tabs and More keep row one, and
     the six extra destinations get a row of their own at full size. */
  /* The row above the bar spans the same width the bar does, so the six
     destinations get full size rather than a share of eleven. */
  .tab-more{width:calc(100vw - 24px);justify-content:space-between;
    bottom:calc(100% + 6px)}
  .tab-more .tab{min-width:0;flex:1;padding-left:2px;padding-right:2px}
  /* Six labels share the second row and "Community" is the one that does not
     fit its share of it. Dropping the tracking buys most of it back; the vw
     cap covers the rest so a 360px Android does not run its labels together.
     min() rather than a breakpoint ladder: the row gets narrower smoothly,
     so the type that has to fit it should too. Above phone width the 10px
     cap always wins, so nothing changes for anybody else. */
  .tab-more .tab span{letter-spacing:0;font-size:min(10px,2.5vw)}
}

/* The host pages all carry a global reduced-motion reset, but the bar must
   not depend on one being there: this file is meant to be the whole widget. */
@media(prefers-reduced-motion:reduce){
  .tabbar,.tab,.tab-more{transition-duration:.001ms}
}

/* ---- light-mode corrections ---- */
html[data-theme="light"] .tabbar{
  background:rgba(255,255,255,.88);
  border-color:rgba(31,42,68,.10);
  /* the dark drop shadow read as a hard band under the pill */
  box-shadow:0 2px 8px rgba(31,42,68,.08), 0 14px 34px rgba(31,42,68,.12),
             inset 0 1px 0 rgba(255,255,255,.9)}
html[data-theme="light"] .tab{color:rgba(17,24,39,.5)}
html[data-theme="light"] .tab:hover{color:rgba(17,24,39,.78)}
html[data-theme="light"] .tab[aria-current="page"]{color:var(--secondary);background:rgba(181,37,85,.09)}
html[data-theme="light"] .tab .badge{box-shadow:0 0 0 2px #fff}
