/* The product bar (templates/_bar.html): Spotter's circuit-green strip across the top of the dashboard
   and of Open WebUI's pages. Loaded by the dashboard's pages and by gui/chat/loader.js on Open WebUI's, so
   it carries its own colors and font: Open WebUI's pages have none of dashboard.css. The font resolves
   next to this file (/dashboard/static/fonts/), on either site. */

@font-face { font-family: "Archivo"; src: url("fonts/Archivo-Variable.woff2") format("woff2"); font-weight: 100 900;
             font-stretch: 62% 125%; font-display: swap; }

.pbar {
  --pbar-circuit: #133F31;                  /* the brand field: the same string as the dashboard's circuit token */
  --pbar-ink: #F1F2EF;                      /* on circuit: the lockup's line, the chosen tab, the chosen theme */
  --pbar-soft: #A6BCB0;                     /* words at rest, 5.9:1 on circuit */
  --pbar-line: #0B2A20;                     /* the 1px line the bar closes with */
  --pbar-edge: #6F9483;                     /* the theme choice's outline, 3.5:1 on circuit */
  --pbar-signal: #E8A55A;                   /* the mark's call dot, 5.6:1 on circuit */
  --pbar-row: 56px; --pbar-note: 0px;       /* the bar's row, and the in-the-building line when it wraps below */
  position: relative; z-index: 30; height: calc(var(--pbar-row) + var(--pbar-note));
  background: var(--pbar-circuit); color: var(--pbar-ink); border-bottom: 1px solid var(--pbar-line);
  font: 400 13px/1.4 "Archivo", "Helvetica Neue", Arial, sans-serif; font-stretch: 100%;
  -webkit-font-smoothing: antialiased; box-sizing: content-box;
}
/* Night: the dashboard's Dark (<html data-theme="dark">), or System on a device set to dark (app/theme.py).
   A lighter circuit, so the field still reads as green on the near-black paddock, with its words and
   outline lifted to keep their contrast (soft 5.8:1, the outline 3.8:1). :where() keeps both at the
   weight of a plain .pbar, so over Open WebUI, which has no data-theme, custom.css's own light and dark
   (Open WebUI's setting) still win. */
:where(:root[data-theme="dark"]) .pbar { --pbar-circuit: #194E3D; --pbar-ink: #EDEFEA; --pbar-soft: #BDCDC4; --pbar-line: #2B6A55; --pbar-edge: #8AAB9B; }
@media (prefers-color-scheme: dark) {
  :where(:root:not([data-theme="light"])) .pbar { --pbar-circuit: #194E3D; --pbar-ink: #EDEFEA; --pbar-soft: #BDCDC4; --pbar-line: #2B6A55; --pbar-edge: #8AAB9B; }
}
.pbar *, .pbar *::before, .pbar *::after { box-sizing: border-box; }

/* The row lines up with the page under it: content 1320px at most, inside 32px gutters (16px on phones). */
.pbar-in { max-width: 1384px; height: 100%; margin: 0 auto; padding: 0 32px; display: flex; flex-wrap: wrap;
           align-items: stretch; align-content: flex-start; column-gap: 24px; }
/* The name holds the row's height itself, so the row stands with or without the tabs (sign-in has none).
   It starts from nothing and grows to its own width where there's room: a long name on a narrow phone
   is cut short with an ellipsis, rather than pushing the tabs out of the bar onto a row of their own.
   Its 10px sides, given back by the margins, keep the focus ring clear of the letters and the mark. */
.pbar-name { flex: 1 1 0; max-width: max-content; align-self: flex-start; min-width: 0; overflow: hidden; white-space: nowrap;
             text-overflow: ellipsis; margin: 0 -10px; padding: 0 10px; color: var(--pbar-ink); text-decoration: none;
             font: 600 15px/var(--pbar-row) "Archivo", "Helvetica Neue", Arial, sans-serif; font-stretch: 125%;
             letter-spacing: .14em; text-transform: uppercase; }
/* Spotter's lockup, 22px tall (169.6px wide). Where the row can't give it all of that, it scales down
   whole, to the brand's smallest lockup (120px wide), then shows the mark alone at full size: never a
   logotype cut through a letter. The link is the container the queries ask; the SVG slices from its
   start, so at the mark's own width only the mark shows. */
.pbar-lockup { display: flex; align-items: center; height: var(--pbar-row); min-width: 42px; max-width: 190px;
               container: pbar-lockup / inline-size; }
.pbar-logo { display: block; flex: none; width: 169.6px; height: 22px; overflow: hidden; }
.pbar-dot { fill: var(--pbar-signal); }
/* Hangtime in the bar (DESIGN.md, Motion): while the next page is on its way, the lockup's own dot takes the line,
   a ground-colored gap under it so it reads on the line. .is-busy comes from dashboard.js or gui/chat/loader.js,
   300ms after the person set off. It starts at the hold (-.351s), on the dot it stands in for: nothing jumps. */
.pbar-gap, .pbar-car { opacity: 0; }
.pbar.is-busy .pbar-dot { opacity: 0; }
/* The car settles in from 2px past the mark's right side and leaves 2px past its left, inside the name's 10px
   sides: unclipped while it laps. (Narrower than the brand's smallest lockup the logotype is display: none, so
   nothing else shows past the box.) */
.pbar.is-busy .pbar-logo { overflow: visible; }
.pbar.is-busy .pbar-gap { stroke: var(--pbar-circuit); animation: pbar-drive 2.6s linear -.351s infinite, pbar-show 2.6s linear -.351s infinite; }
.pbar.is-busy .pbar-car { stroke: var(--pbar-signal); animation: pbar-drive 2.6s linear -.351s infinite, pbar-show 2.6s linear -.351s infinite; }
@keyframes pbar-drive {
  0%    { stroke-dashoffset: 0;        animation-timing-function: cubic-bezier(.16, 1, .3, 1); }
  13.5% { stroke-dashoffset: -4;       animation-timing-function: linear; }
  34.5% { stroke-dashoffset: -4;       animation-timing-function: cubic-bezier(.4, 0, .2, 1); }
  88.5% { stroke-dashoffset: -146.549; }
  100%  { stroke-dashoffset: -146.549; }
}
@keyframes pbar-show {
  0%    { opacity: 0; animation-timing-function: cubic-bezier(.16, 1, .3, 1); }
  11.5% { opacity: 1; }
  79%   { opacity: 1; animation-timing-function: cubic-bezier(.4, 0, 1, 1); }
  88.5% { opacity: 0; }
  100%  { opacity: 0; }
}
@container pbar-lockup (width < 169.5px) {
  .pbar-logo { width: 100cqw; height: calc(100cqw * 38.4 / 296); }
}
@container pbar-lockup (width < 120px) {
  .pbar-logo { width: 22px; height: 22px; }
  .pbar-word { display: none; }
}

/* Tabs, the in-the-building line, and Sign out: Expanded capitals, 12px, tracked .16em, soft at rest and
   ink when current or under the pointer. Each control's right padding gives back the tracking after its
   last letter, so the words sit centered and the current tab's 2px underline runs exactly under them. */
.pbar-tabs { display: flex; height: var(--pbar-row); margin: 0; padding: 0; list-style: none; flex: none; }
.pbar-tabs a { position: relative; display: flex; align-items: center; height: 100%; padding: 0 calc(14px - .16em) 0 14px;
               color: var(--pbar-soft); text-decoration: none; font: 500 12px/1 "Archivo", "Helvetica Neue", Arial, sans-serif;
               font-stretch: 125%; letter-spacing: .16em; text-transform: uppercase;
               transition: color .18s cubic-bezier(.16, 1, .3, 1); }
.pbar-tabs a:hover { color: var(--pbar-ink); }
.pbar-tabs a[aria-current="page"] { color: var(--pbar-ink); }
.pbar-tabs a[aria-current="page"]::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: 0; height: 2px;
                                           background: var(--pbar-ink); }
.pbar-trust { height: var(--pbar-row); margin: 0 0 0 auto; flex: none; display: inline-flex; align-items: center; gap: 8px;
              color: var(--pbar-soft); font: 500 12px/16px "Archivo", "Helvetica Neue", Arial, sans-serif; font-stretch: 100%;
              white-space: nowrap; }
.pbar-ic { display: block; flex: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6;
           stroke-linecap: round; stroke-linejoin: round; }
/* The ring sits inside the tab: the tabs run the bar's full height, so a ring outside would be cut off
   by the window's top edge and lost in the line below. The bar's own light ink, since signal is too
   dark to read on circuit by Day. */
.pbar a:focus-visible { outline: 2px solid var(--pbar-ink); outline-offset: -3px; }

/* The theme choice, on the dashboard's pages only (app/theme.py): System, Light, and Dark as a stadium
   segmented control in the bar's own colors, after the in-the-building line. At rest soft, ink under the
   pointer, and the chosen one filled ink, as a chosen segment on the paddock is. Each names itself to a
   screen reader (aria-label) and in a tooltip, and says which one is chosen (aria-pressed). */
.pbar-theme { display: flex; align-items: center; height: var(--pbar-row); margin: 0; flex: none; }
.pbar-seg { display: flex; gap: 2px; padding: 2px; border: 1px solid var(--pbar-edge); border-radius: 12px; }
.pbar-seg button { display: grid; place-items: center; width: 34px; height: 28px; margin: 0; padding: 0; border: 0;
                   border-radius: 50%; background: none; color: var(--pbar-soft); cursor: pointer;
                   transition: color .18s cubic-bezier(.16, 1, .3, 1), background-color .18s cubic-bezier(.16, 1, .3, 1); }
.pbar-seg button:hover { color: var(--pbar-ink); }
.pbar-seg button[aria-pressed="true"] { background: var(--pbar-ink); color: var(--pbar-circuit); }
.pbar-seg button:focus-visible { position: relative; outline: 2px solid var(--pbar-ink); outline-offset: 2px; }
@media (forced-colors: active) {   /* the chosen one keeps its fill where the system draws the colors, as the follow-up's choices do */
  .pbar-seg button[aria-pressed="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .pbar-tabs a[aria-current="page"]::after { forced-color-adjust: none; background: LinkText; }   /* the current tab's underline too */
  .pbar.is-busy .pbar-car { forced-color-adjust: none; stroke: Highlight; }   /* the hangtime's car, on a Canvas gap */
  .pbar.is-busy .pbar-gap { forced-color-adjust: none; stroke: Canvas; }
}

/* Sign out, on the dashboard's pages only (the chat's menu is out of reach): the row's last word, in the
   tabs' capitals and colors, soft at rest and ink under the pointer. A form's button, so it works without
   the script. Its words line up with the gutter; its touch area runs the bar's height. */
.pbar-out { display: flex; height: var(--pbar-row); margin: 0 -14px 0 0; flex: none; }
.pbar-out button { height: 100%; margin: 0; padding: 0 calc(14px - .16em) 0 14px; border: 0; background: none;
                   color: var(--pbar-soft); cursor: pointer; font: 500 12px/1 "Archivo", "Helvetica Neue", Arial, sans-serif;
                   font-stretch: 125%; letter-spacing: .16em; text-transform: uppercase;
                   transition: color .18s cubic-bezier(.16, 1, .3, 1); }
.pbar-out button:hover { color: var(--pbar-ink); }
.pbar-out button:focus-visible { outline: 2px solid var(--pbar-ink); outline-offset: -3px; }   /* inside, as the tabs' */

/* Narrower, the in-the-building line takes its own short row under the name and tabs: privacy stays
   visible on every phone, never a bare shield. In Expanded capitals the line, the lockup, and two tabs
   need about 790px of row, so it moves at 800px (gui/chat/custom.css holds the same width for the bar's
   room; tests/test_theme.py keeps the two in step). */
@media (max-width: 800px) {
  .pbar { --pbar-note: 22px; }
  .pbar-trust { order: 3; flex: 0 0 100%; height: var(--pbar-note); margin: 0; align-items: center; gap: 6px;
                font-size: 12px; }
  .pbar-trust .pbar-ic { width: 14px; height: 14px; }
}
/* The dashboard's bar also holds the theme choice and Sign out, so there the line takes its own row
   sooner, at 1200px and below, and the two end the first row: in Expanded capitals the first row needs
   about 1110px (1200px with the Admin tab) to keep the whole lockup beside everything else. */
@media (max-width: 1200px) {
  .pbar[data-on="dashboard"] { --pbar-note: 22px; }
  .pbar[data-on="dashboard"] .pbar-trust { order: 3; flex: 0 0 100%; height: var(--pbar-note); margin: 0; align-items: center;
                                           gap: 6px; font-size: 12px; }
  .pbar[data-on="dashboard"] .pbar-trust .pbar-ic { width: 14px; height: 14px; }
  .pbar-theme { margin-left: auto; }
}
@media (max-width: 640px) {
  .pbar { --pbar-row: 52px; }
  .pbar-in { padding: 0 16px; column-gap: 12px; }
  .pbar-name { font-size: 13px; letter-spacing: .12em; }
  .pbar-tabs a { padding: 0 calc(10px - .16em) 0 10px; }
  .pbar-tabs a[aria-current="page"]::after { left: 10px; right: 10px; }
  /* A phone's first row holds the name, the tabs, and Sign out: the choice ends the second, after the
     line, which wraps to two lines there rather than push the choice off. The row is a finger's 44px. */
  .pbar[data-on="dashboard"] { --pbar-note: 44px; }
  .pbar[data-on="dashboard"] .pbar-trust { flex: 1 1 calc(100% - 124px); min-width: 0; align-items: center; line-height: 14px;
                                           white-space: normal; }   /* 112px choice, 12px gap */
  .pbar-theme { order: 4; height: var(--pbar-note); }
  /* The choice is drawn 2px slimmer to sit clear of the row's edges; each button's touch area still
     runs the row's full height. */
  .pbar-seg button { position: relative; height: 26px; }
  .pbar-seg button::before { content: ""; position: absolute; inset: -9px -1px; }
  .pbar-lockup { min-width: 44px; }   /* the mark alone, a finger wide */
  .pbar-out { margin: 0 -10px 0 auto; }   /* so Sign out ends the first row, after the name and the tabs */
  .pbar-out button { padding: 0 calc(10px - .16em) 0 10px; }
}
/* The narrowest phones: the line runs to three lines, so its row grows to hold them clear of the tabs. */
@media (max-width: 335px) {
  .pbar[data-on="dashboard"] { --pbar-note: 48px; }
}
/* A phone's dashboard bar shows the mark alone, right beside the tabs: the lockup, the tabs, and Sign out
   never fit one row there. A bar with more than one tab (Dashboard · Settings · Admin: the GM's Settings,
   Open WebUI's admins' Admin) sets its words a size down on phones, then a width narrower on the narrowest,
   so the tabs and Sign out always share the first row, still in the bar's tracked capitals. A bar with all
   three steps down sooner, and on the dashboard's own bar (its theme choice and Sign out on the same row)
   from 720px. The widths are measured, Day and Night, from 320px up (each step's words, padding and gap). */
@media (max-width: 480px) {
  .pbar[data-on="dashboard"] .pbar-lockup { flex: none; width: 42px; }
  .pbar:has(.pbar-tabs li + li) :is(.pbar-tabs a, .pbar-out button) { font-size: 11px; letter-spacing: .14em;
                                                                     padding: 0 calc(8px - .14em) 0 8px; }
  .pbar:has(.pbar-tabs li + li) .pbar-tabs a[aria-current="page"]::after { left: 8px; right: 8px; }
  .pbar:has(.pbar-tabs li + li) .pbar-out { margin-right: -8px; }
}
@media (max-width: 400px) {
  .pbar:has(.pbar-tabs li + li) :is(.pbar-tabs a, .pbar-out button) { font-stretch: 100%; letter-spacing: .1em;
                                                                     padding: 0 calc(7px - .1em) 0 7px; }
  .pbar:has(.pbar-tabs li + li) .pbar-tabs a[aria-current="page"]::after { left: 7px; right: 7px; }
  .pbar:has(.pbar-tabs li + li) .pbar-out { margin-right: -7px; }
}
@media (max-width: 720px) {
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) :is(.pbar-tabs a, .pbar-out button) {
    font-size: 11px; letter-spacing: .12em; padding: 0 calc(7px - .12em) 0 7px; }
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-tabs a[aria-current="page"]::after { left: 7px; right: 7px; }
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-out { margin-right: -7px; }
}
@media (max-width: 460px) {
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) :is(.pbar-tabs a, .pbar-out button) {
    font-stretch: 100%; letter-spacing: .08em; padding: 0 calc(6px - .08em) 0 6px; }
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-tabs a[aria-current="page"]::after { left: 6px; right: 6px; }
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-out { margin-right: -6px; }
}
@media (max-width: 374px) {
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-in { column-gap: 10px; }   /* the mark's own 10px side, no closer */
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) :is(.pbar-tabs a, .pbar-out button) {
    font-stretch: 87.5%; letter-spacing: .06em; padding: 0 calc(5px - .06em) 0 5px; }
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-tabs a[aria-current="page"]::after { left: 5px; right: 5px; }
  .pbar[data-on="dashboard"]:has(.pbar-tabs li + li + li) .pbar-out { margin-right: -5px; }
}
@media (prefers-reduced-motion: reduce) {   /* the hangtime is the still lockup: its dot stays where it is */
  .pbar-tabs a, .pbar-seg button, .pbar-out button { transition: none; }
  .pbar.is-busy :is(.pbar-car, .pbar-gap) { animation: none; opacity: 0; }
  .pbar.is-busy .pbar-dot { opacity: 1; }
}

/* Keyboard entry point, visible only when focused. */
.skip-content { position:fixed; top:8px; left:8px; z-index:1000; padding:12px 16px; background:var(--paddock,#f1f2ef); color:var(--ink,#0f1512); transform:translateY(-180%); }
.skip-content:focus { transform:none; outline:3px solid var(--signal,#8f5a2f); outline-offset:2px; }

/* Cockpit-linked pages share the native header's inset 32px theme highlights. */
.cockpit-ui .pbar-theme { height:44px; align-self:center; margin-left:auto; }
.cockpit-ui .pbar-seg {
  height:44px; padding:0; border:0; border-radius:10px;
  box-shadow:inset 0 0 0 1px var(--pbar-edge);
}
.cockpit-ui .pbar-seg button {
  position:relative; isolation:isolate; width:44px; height:44px; background:none;
}
.cockpit-ui .pbar-seg button::before {
  content:""; position:absolute; inset:6px; border-radius:50%; z-index:-1;
}
.cockpit-ui .pbar-seg button:hover::before { background:#ffffff1a; }
.cockpit-ui .pbar-seg button[aria-pressed="true"]::before { background:var(--pbar-ink); }
.cockpit-ui .pbar-seg button svg { width:18px; height:18px; }
@media (forced-colors:active) {
  .cockpit-ui .pbar-seg button[aria-pressed="true"]::before { background:Highlight; }
}
