/* Standard module — Top bar (Project Rules, v0.6 batch).
   One shared copy for every report page; markup is built by topbar.js initTopbar().
   Tokens come from tokens.css — no local :root block. */

.topbar{position:sticky;top:0;z-index:var(--z-bar,40);height:56px;display:flex;align-items:center;gap:10px;padding:0 12px;
  background:var(--bar-tint-raised);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-bottom:1px solid var(--hairline)}
.topbar svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* Improvements 0.82 Part 4 #22: every icon button carries the same visible
   outline as the text buttons beside it. Undo/redo were borderless, so their
   footprint was invisible and the 19px glyph read as a control half the size
   of Save — in both text-size modes, since zoom scales everything equally. */
.tb-icon{width:var(--touch-min);height:var(--touch-min);border-radius:var(--r-md);border:1px solid var(--hairline-strong);background:transparent;color:var(--text-2);
  display:inline-flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}
.tb-icon:hover{background:var(--ink-2);color:var(--text-1)}
.tb-icon:active{transform:scale(.94)}
.tb-icon:disabled{opacity:.28;cursor:not-allowed;background:transparent;transform:none}
.tb-icon[hidden]{display:none}
/* v0.68: the report-type/building title text is removed from the sticky top
   bar (it's shown once at the top of the report body instead) — the element
   and setTitle() API stay so callers don't need to change, they just render
   nothing. Progress takes over that space and is always visible. */
.tb-title{display:none}
/* The NAVIGATION bar (topbar.js cfg.nav, v0.85.55): property, handbook, Time.
   There the title IS shown — it is the page's name, and the flex spacer that
   pushes the sync button and the account chip to the right. */
.topbar.tb-nav .tb-title{display:block;min-width:0;flex:1}
.topbar.tb-nav .tb-title b{display:block;font-size:15px;font-weight:700;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar.tb-nav .tb-title span{display:block;font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;
  color:var(--text-3);text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar.tb-nav .tb-title span:empty{display:none}
/* The track FILLS the free space, as the monthly's own bar always has (v0.68).
   It was a fixed 96px stub pinned left, and the pump test pinned it right, which
   left a dead gap in the middle of the bar on a wide screen. */
.tb-progress{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex:1;min-width:0}
.tb-progress .bar{flex:1;min-width:40px;height:5px;background:var(--ink-3);border-radius:99px;overflow:hidden}
.tb-progress .bar i{display:block;height:100%;background:var(--progress);border-radius:99px;transition:width .3s}
.tb-progress span{font-family:var(--font-mono);font-size:11px;color:var(--text-2);min-width:30px;text-align:right}
/* v0.84 #2/#3: the sync pill is a BUTTON — dot, word, refresh arrow — and it
   is never hidden (see topbar.js's header). 40px tall like every other control
   on the bar; the arrow spins while a refresh runs; OFFLINE is the warn tone
   on the dot AND the ring so it reads without the word. */
.sync{display:inline-flex;align-items:center;gap:7px;height:var(--touch-min);font-family:var(--font-mono);font-size:10px;
  letter-spacing:.06em;color:var(--text-3);background:var(--ink-0);border:1px solid var(--hairline);
  border-radius:999px;padding:0 10px 0 12px;flex-shrink:0;cursor:pointer;font-weight:600}
.sync:hover{color:var(--text-1);border-color:var(--hairline-strong)}
.sync:disabled{cursor:default}
.sync .d{width:6px;height:6px;border-radius:99px;background:var(--pass);flex:none}
.sync .sync-r{width:15px;height:15px;stroke-width:2.2;flex:none;opacity:.75}
.sync:hover .sync-r{opacity:1}
/* 0.84 audit, rule 10: sync is --blue (tokens.css names it for sync),
   offline is the pending grey — never the building's amber. */
.sync.syncing{color:var(--blue)}
.sync.syncing .d{background:var(--blue);animation:tb-pulse 1s infinite}
.sync.off{color:var(--state-pending);border-color:var(--state-pending)}
.sync.off .d{background:var(--state-pending);animation:tb-pulse 1.2s infinite}
.sync.spin .sync-r{animation:tb-spin .8s linear infinite;opacity:1}
@keyframes tb-pulse{50%{opacity:.25}}
@keyframes tb-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.sync.spin .sync-r{animation:none}}
.tb-sep{width:1px;height:24px;background:var(--hairline-strong);flex-shrink:0;margin:0 2px}
.tb-btn{height:var(--touch-min);padding:0 15px;border-radius:var(--r-md);border:1px solid var(--hairline-strong);background:transparent;color:var(--text-1);
  font-family:var(--font-ui);font-size:14px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:7px;flex-shrink:0}
/* `hidden` must actually hide. The rule above sets display:inline-flex from a
   CLASS, which outranks the UA stylesheet's [hidden]{display:none} — so
   tb.setReadonly(true), whose whole point is to REMOVE Save and Submit rather
   than merely disable them (see the note on setReadonly in topbar.js), left both
   buttons on screen over a read-only report. They were also disabled, so nothing
   could be written, but a visibly greyed-out Save is exactly the "why can't I
   press this?" invitation that setReadonly was written to avoid. Affects every
   page using the shared bar — pump_test viewing a submitted report, and the
   annual's read-only shell. */
.tb-btn[hidden]{display:none}
.tb-btn:hover{background:var(--ink-2)}
.tb-btn:active{transform:scale(.97)}
.tb-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}
.tb-btn svg{width:17px;height:17px}
.tb-btn.saved{color:var(--pass);border-color:var(--pass)}
.tb-primary{background:var(--flame);border-color:var(--flame);color:#fff}
.tb-primary:hover{background:var(--flame-hover)}
/* Part 8 #42 (annual): every section is in — Submit pulses twice, then keeps a
   quiet halo. Nothing moves under prefers-reduced-motion. */
.tb-submit.tb-ready{box-shadow:0 0 0 3px var(--flame-subtle);animation:tbReady .9s ease-out 2}
@keyframes tbReady{0%{box-shadow:0 0 0 0 var(--flame-subtle)}60%{box-shadow:0 0 0 9px transparent}100%{box-shadow:0 0 0 3px var(--flame-subtle)}}
@media (prefers-reduced-motion:reduce){.tb-submit.tb-ready{animation:none}}
.tb-more{position:relative;flex-shrink:0}
.tb-menu{position:absolute;top:50px;right:0;background:var(--ink-2);border:1px solid var(--hairline-strong);border-radius:var(--r-lg);
  padding:6px;min-width:200px;box-shadow:0 18px 44px var(--shadow);display:none;z-index:var(--z-popover,60)}
.tb-menu.on{display:block}
.tb-menu button{display:flex;width:100%;align-items:center;gap:11px;background:none;border:none;color:var(--text-1);
  font-family:var(--font-ui);font-size:14px;font-weight:600;padding:11px 12px;border-radius:9px;cursor:pointer;text-align:left}
.tb-menu button svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.tb-menu button:hover{background:var(--ink-3)}
.tb-menu button.danger{color:var(--fail)}
.tb-menu button.danger:hover{background:var(--fail-subtle)}
.tb-menu .mnsep{height:1px;background:var(--hairline);margin:5px 6px}
/* 0.85 Part 12 #13 (Rob): the COMPACT bar is for phones. It used to start
   at 760px, which caught an iPad mini in portrait (744) with room to spare —
   no SYNCED word, no rule between undo and redo. The full bar measures ~600px
   of controls and fits a 701px window even under Large text's zoom
   (measured, no overflow), so the compact tier starts below 700: every iPad at full width keeps the full bar, a phone in
   landscape and a narrow Split View do not. */
@media(max-width:700px){
  .topbar{padding:0 8px;gap:6px}
  /* v0.84 #2: NOT display:none any more — the pill stays at every width.
     Under the tier the word goes, the dot and arrow stay. */
  .sync{padding:0 9px 0 11px;gap:6px}
  .sync .sync-t{display:none}
  .tb-sep{display:none}
  .tb-progress .bar{width:64px}
  .tb-btn{padding:0 12px;font-size:13px}
}
/* Above the phone tier these two are redundant with the arrows on the bar.
   MUST stay above the 480px block: equal specificity, so source order decides,
   and below it they would cancel the very rule that reveals them. */
.tb-mi-undo,.tb-mi-redo{display:none}
.tb-mi-hsep{display:none}
/* a separator only separates — with nothing under it, it is a stray line */
.tb-menu .mnsep:last-child{display:none}
.tb-menu button:disabled{opacity:.38;cursor:not-allowed}
/* PHONE (v0.85.6). Every child of this bar is flex-shrink:0 and there is no
   flex-wrap, so the bar was pinned at its max-content width — ~508px of controls
   in a 412px viewport (a Pixel 8), and because .topbar is position:sticky the
   excess dragged the whole document sideways. Reported from the field on the
   hydrant and pump test.
   Budget, not taste: back 44 + % text 30 + sync 41 + Save 52 + Submit 66 + ⋮ 44
   + account chip 42 = 319, plus 6 gaps x 4 and 12 padding = ~355. That leaves
   headroom for html[data-text="large"] (tokens.css zoom:1.14), which leaves a
   412px phone ~361 CSS px while these queries still see 412.
   Undo/redo are MOVED, not dropped — topbar.js duplicates them into the ⋮ menu,
   and losing undo on a touch device would be worse than the scroll it fixes. */
@media(max-width:480px){
  .topbar{padding:0 6px;gap:4px}
  .tb-progress .bar{display:none}      /* the % text carries the same fact */
  .tb-undo,.tb-redo{display:none}
  .tb-mi-undo,.tb-mi-redo{display:flex}
  .tb-mi-hsep{display:block}
  /* the ⋮ is hidden by syncMore() when it holds nothing BUT history; down here
     the history items are real, so bring it back */
  .tb-more.tb-hist[hidden]{display:block}
  .tb-btn{padding:0 10px;font-size:13px}
}
@media print{.topbar{display:none!important}}
/* iOS standalone: sit below the status bar. --status-top (tokens.css, Part 12
   #50E) is 0 everywhere else, so this is the one rule for every window.
   Kept last in the file so it beats the max-width block's padding shorthand. */
.topbar{height:calc(56px + var(--status-top,0px));padding-top:var(--status-top,0px)}
