/* ==========================================================================
   Bottom navigation bar (mobile/tablet)

   A permanent, space-reserving app-style tab bar. Loaded only on requests
   where inc/bottom-nav.php renders it, which is what makes the height
   contract below safe: where the bar is absent this file is absent with it,
   and --pp-bottom-nav-h keeps its 0px default from style.css.

   THE CONTRACT
   ------------
   The theme publishes one custom property and every bottom-anchored element
   in the stack reads it:

       bottom: calc(16px + var(--pp-bottom-nav-h, 0px));

   It is 0px wherever the bar is not on screen — desktop, Topic Sessions focus
   mode, the zoom-guard hide step, or a page the bar does not load on — so
   every consumer rule is inert by default and no plugin needs to know whether
   this theme is present. That replaces the old "suspend it, don't dodge it"
   arrangement, which existed only because the previous bar's height was
   unknowable (it wrapped to two rows) and it was absent most of the time.
   Both of those are gone: one row, known height, always there.

   NO MOTION, NO SCRIPT
   --------------------
   The bar never appears or disappears, so there is nothing to transition and
   no prefers-reduced-motion branch to write. The scroll listener, the 2.5s
   hide timer and the slide transform are deleted rather than tuned.
   ========================================================================== */

/* Desktop and up: no bar. --pp-bottom-nav-h keeps its 0px default. */
.pp-bottom-nav {
  display: none;
}

@media (max-width: 1024px) {
  :root {
    /* Content is 2 marker + 4 padding + 24 icon + 4 gap + ~15.6 label
       (0.85rem @ 1.15) + 4 padding = ~53.6, centred in 56. Kept in sync with
       PP_BOTTOM_NAV_HEIGHT in inc/bottom-nav.php. */
    --pp-bottom-nav-h: 56px;
  }

  /* Reserve the bar's own space so it can never overlap content. This is the
     whole point of the refactor: the previous bar was fixed over the page
     with nothing reserving room, so it covered cloze gaps and the
     Submit/See Answers/Restart row and took their taps.

     `html body` rather than `body` on purpose — Blocksy emits its own
     `body { padding-bottom: … }` at the same specificity, and which of the
     two wins would otherwise depend on stylesheet order. */
  html body {
    padding-bottom: calc(var(--pp-bottom-nav-h) + env(safe-area-inset-bottom, 0px));
  }

  .pp-bottom-nav {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    box-sizing: border-box;
    height: calc(var(--pp-bottom-nav-h) + env(safe-area-inset-bottom, 0px));
    /* Keeps the tap targets clear of the iPhone home indicator. Nothing in
       the stack used env() before this; any element fixed to the bottom edge
       needs it. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--theme-palette-color-4);
    z-index: var(--pp-z-bottom-nav, 900);
    /* Popover tier, inverted: the bar is anchored to the bottom edge, so the
       tier's downward y-offset points the wrong way and the sign flips. Same
       blur, spread and alpha. A bar sitting over running text is doing a
       dropdown's job, not a resting button's, so the Resting tier's 0.08 is
       too faint to separate it from a page of type. */
    box-shadow: 0 -8px 24px rgba(var(--pp-steel-7-rgb), 0.20);
  }

  .pp-bottom-nav__list {
    display: flex;
    align-items: stretch;
    height: 100%;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /* Equal columns, sized from the item count. `min-width: 0` so the split is
     governed by flex rather than by the labels' intrinsic width. */
  .pp-bottom-nav__item {
    flex: 1 1 0;
    min-width: 0;
  }

  .pp-bottom-nav__link {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    box-sizing: border-box;
    height: 100%;
    /* Standalone control (STYLING.md § Touch Targets). The column is ~64px
       wide at 320px, so both axes clear the floor with room. */
    min-height: 44px;
    padding: 4px;
    text-decoration: none;
    /* The selected marker exists at rest so selecting shifts nothing —
       STYLING.md § Tabs. A border rather than an absolutely positioned
       pseudo-element, for the reason that section gives: a pseudo-element
       drawn outside the padding box is the first thing an overflow clips. */
    border-top: 2px solid transparent;
    /* Muted mark on a dark fill: --pp-steel-1 at 0.72 composites to
       rgb(166,177,182) over --theme-palette-color-4, which is 8.2:1 —
       comfortably AA at this size while still reading as secondary against
       the active item's 17.5:1. See the FLAGGED note at the foot of this file. */
    color: rgba(var(--pp-steel-1-rgb), 0.72);
  }

  /* Touch-only surface: no hover state. Focus is keyboard-only and takes the
     standard ring. `outline-offset` is negative so the ring stays inside the
     bar rather than being clipped by its top edge. */
  .pp-bottom-nav__link:focus-visible {
    outline: 2px solid var(--pp-focus-ring);
    outline-offset: -2px;
    border-radius: 8px;
  }

  .pp-bottom-nav__icon {
    display: block;
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
  }

  /* The three CPT glyphs are shared with the archive cards and carry no
     stroke attributes of their own — the consumer supplies them, exactly as
     css/archive-cards.css does. The Home and Recall glyphs authored in
     inc/bottom-nav.php are stroked the same way, so one rule serves all five. */
  .pp-bottom-nav__icon svg {
    display: block;
    width: 100%;
    height: 100%;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  /* Sentence case, never uppercase: uppercase costs ~10% width and legibility,
     which is the wrong trade on the surface this refactor exists to fix.
     0.85rem is the established secondary/UI-chrome size; "Practice" measures
     ~52px in Inter, inside a 64px column on a 320px phone.
     No font-family declaration — an <a> inherits the site face already. */
  .pp-bottom-nav__label {
    font-size: 0.85rem;
    line-height: 1.15;
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* Active section. A tab bar that shows where you *are* is orienting; one
     that only shows where you can go is another menu.

     Two signals, because the accent alone is not enough on this ground:
     --theme-palette-color-5 on --theme-palette-color-4 is 3.08:1, which
     clears the 3:1 required of a graphical indicator but is under AA for
     text. So the accent draws the marker and the label carries the contrast. */
  .pp-bottom-nav__link.is-active {
    color: var(--theme-palette-color-8);
    border-top-color: var(--theme-palette-color-5);
  }
}

/* --------------------------------------------------------------------------
   Zoom guard

   Height queries deliberately unpaired with `min-width: 769px`. That rule
   exists because content taller than a phone viewport is normal and should
   scroll. A fixed bar is not content: it permanently subtracts viewport, and
   under page zoom — which is exactly what a low-vision member is running —
   that subtraction is the problem. See STYLING.md § Viewport-height
   breakpoints for the stated exception.

   Page zoom shrinks the CSS viewport while the bar's height stays fixed in
   CSS px, so height is what detects it. A 390 x 844 phone reports roughly
   563px tall at 150%, 422px at 200%, 338px at 250%.
   -------------------------------------------------------------------------- */

/* Compact: shrink the chrome, keep the labels. Dropping labels here would
   hand the unlabeled icon row to the one member who most needs the words —
   three of the five glyphs (compass, repeat, message-quote) do not name their
   destination on their own. 48px still clears the 44px touch floor. */
@media (max-width: 1024px) and (max-height: 560px) {
  :root {
    /* 2 marker + 20 icon + 4 gap + ~15.6 label = ~41.6, centred in 44 —
       which is also exactly the standalone-control touch floor, so the
       compact bar cannot shrink past it. */
    --pp-bottom-nav-h: 44px;
  }

  .pp-bottom-nav__icon {
    width: 20px;
    height: 20px;
  }

  /* Vertical padding gives way first; the flex centring keeps the contents
     off both edges without it. */
  .pp-bottom-nav__link {
    padding: 0 4px;
  }
}

/* Hide: past this the bar costs more viewport than it returns. The header
   hamburger remains, so nothing becomes unreachable — and zeroing the
   variable hands the reserved space back at the same moment, so no gap is
   left behind and every floating control returns to its plain 16px inset. */
@media (max-width: 1024px) and (max-height: 460px) {
  :root {
    --pp-bottom-nav-h: 0px;
  }

  .pp-bottom-nav {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   FLAGGED for STYLING.md (see bottom-nav-refactor.md § 6):

   - `rgba(var(--pp-steel-1-rgb), 0.72)` as a MUTED MARK ON A DARK FILL.
     That channel is documented for translucent light *surfaces*, not for
     text, and rule 7 offers only `#fff` for marks on a dark fill with no
     muted counterpart. This is a new role for an existing token and stays
     flagged until validated.
   - The Popover shadow tier inverted for a bottom-anchored element. The
     documented tiers all assume a downward offset.
   - `--pp-z-bottom-nav: 900` — the stacking layer § Z-index asks to have
     defined rather than guessed.
   - `env(safe-area-inset-bottom)`, which nothing in the stack used before and
     which every bottom-anchored element needs.
   - `outline-offset: -2px` rather than the documented `2px`. Not a colour
     deviation (rule 5 is about the ring's colour, which is unchanged): a
     positive offset on an element flush to the viewport edge draws half the
     ring off-screen. Inset is the right answer for edge-anchored controls.
   -------------------------------------------------------------------------- */
