/* shell-bar-skin.css — the taskbar's LOOK, once, for every surface.
 *
 * WHAT THIS IS
 * The visual treatment of the JCOM bar (the CIC Control Center's taskbar,
 * cic/topology/styles.css:699-735 and :1046-1059) rewritten
 * against semantic role classes and the --bar-* tokens in shell-tokens.css.
 * Characterisation and every file:line: .migration/SKIN_jcom.md.
 *
 * WHAT THIS IS NOT
 * It does not know which buttons exist, what order they come in, or what they
 * do. Slots, ordering and behaviour belong to the shell contract
 * (shell.contract.json) and the surface's own JS. This file only answers:
 * what colour, what size, what shape, what type, what motion.
 *
 * ROLE CLASSES (the whole adoption surface — ONE class name)
 *   .shell-bar          the <header>. sticky, one height, chrome + blur.
 *
 * CIC's bar is RENDERED from taskbar.slots and needs only .shell-bar. The other
 * three describe POSITION - which controls cluster, which container grows, which
 * control is last - and position is a fact about the list, so the rendered bar
 * cannot use them and a class restating the order can only go out of date.
 *
 * They are NOT deleted, because this skin is SHARED. musix/shell and
 * jslc/shell still AUTHOR their bars and still carry __slot and __end. I removed
 * these rules in 2d23be8 after checking only CIC's usage, and broke both of those
 * surfaces - the owner reported it as "musix top/nav bar is wrong". A shared
 * stylesheet's consumers are not the ones you happen to be looking at.
 *
 * They are inert for CIC and load-bearing for the authored bars, and they stay
 * until those bars are rendered too.
 */

/* ---------- the bar ---------- */
.shell-bar {
  position: sticky;
  inset: 0 0 auto;
  z-index: 90;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: stretch;
  width: 100%;
  min-height: var(--bar-height);
  margin: 0;
  padding: 0;
  /* THE BAR DEFINES ITS OWN SPACING. --bar-control-gap has existed in
   * shell-tokens.css since the skin was written and was consumed NOWHERE, so
   * the token declared an intent the CSS could never reach and an unrelated
   * page selector decided the bar's layout by accident. Same shape as the
   * icons-only gap: a token describing a state nothing produced. Stating it
   * here means no outside rule can set it without saying .shell-bar. */
  gap: var(--bar-control-gap);
  justify-content: flex-start;
  overflow: hidden;
  border: 0;
  border-bottom: var(--bar-rule);
  background: var(--bar-bg);
  color: var(--bar-fg);
  box-shadow: var(--bar-shadow);
  backdrop-filter: var(--bar-blur);
  -webkit-backdrop-filter: var(--bar-blur);
}

/* Engines without color-mix() get the solid chrome instead of nothing. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .shell-bar { background: var(--bar-bg-solid); }
}

/* LOAD-BEARING FOR AUTHORED BARS ONLY (musix/shell, jslc/shell). Layout only:
 * the per-element divider halves these rules used to carry are deliberately not
 * restored, because dividers are stated as adjacency now and restoring them
 * would bring back the doubled line the owner reported as a half box. */
.shell-bar__group {
  display: flex;
  flex: 0 0 auto;
  align-items: stretch;
  gap: var(--bar-control-gap);
}
.shell-bar__slot {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: nowrap;
  align-items: stretch;
  justify-content: flex-end;
  gap: var(--bar-control-gap);
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
}
.shell-bar__slot::-webkit-scrollbar { display: none; }
.shell-bar__slot[hidden] { display: none; }

/* ---------- every control, whatever element it is ---------- */
.shell-bar :is(button, a, [role="button"]) {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: max-content;
  height: auto;
  min-height: var(--bar-control-height);
  margin: 0;
  padding: var(--bar-control-padding);
  border: var(--bar-control-border);
  border-radius: var(--bar-control-radius);
  background: var(--bar-control-bg);
  color: var(--bar-fg);
  box-shadow: none;
  outline: 0;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--bar-motion);

  /* The acceptance test lives here. Five longhands, five tokens, no
   * shorthand: `font: … inherit` is invalid and silently drops the whole
   * declaration (that is how the JCOM bar ended up in the UA font). */
  font-family: var(--bar-font-family);
  font-size: var(--bar-font-size);
  font-weight: var(--bar-font-weight);
  line-height: var(--bar-line-height);
  letter-spacing: var(--bar-letter-spacing);
  text-transform: var(--bar-text-transform);
  font-synthesis: none;
}

/* A DIVIDER BELONGS TO THE GAP, NOT TO A BUTTON.
 *
 * Every control used to carry `border-right`, and the final one additionally
 * carried a stronger `border-left`. That drew TWO lines 31px apart in the last
 * gap - the owner reported it as "a half box between the rightmost button and
 * the one just to the left of it" - and it was reachable because a decoration
 * that lives on a button cannot know what is beside it.
 *
 * Stated as adjacency, one line per gap is not a rule that is followed: it is
 * the only thing the selector can produce. There is no first control to
 * special-case and no last control to special-case, so emptying any slot
 * cannot leave a stray edge.
 *
 * The right group's leading divider is stronger because it separates two
 * groups rather than two controls; it is still exactly one line, because it
 * REPLACES the adjacency divider at that position rather than adding to it. */
/* KEYED TO THE SLOT, NOT THE ELEMENT. Every bar occupant is stamped
 * data-taskbar-slot by the renderer, and three of the JSLC shell occupants
 * are a <div> and a <select> rather than buttons - so an adjacency rule
 * written in terms of buttons silently skipped them and left those gaps
 * undrawn. The slot attribute is what every occupant has in common, which is
 * the whole point of rendering the bar from a slot list. */
.shell-bar__scroll-lane {
  display: flex;
  flex: 1 1 auto;
  min-inline-size: 0;
  align-items: stretch;
  gap: var(--bar-control-gap);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-padding-inline-end: var(--bar-control-gap);
  padding-inline-end: var(--bar-control-gap);
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--bar-fg) 55%, transparent) transparent;
}
.shell-bar__scroll-lane::-webkit-scrollbar { height: .22rem; }
.shell-bar__scroll-lane::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--bar-fg) 55%, transparent); border-radius: 1rem; }
.shell-bar__scroll-lane > [data-taskbar-slot] + [data-taskbar-slot] {
  border-left: var(--bar-control-divider);
}
.shell-bar__scroll-lane > [data-taskbar-slot][data-bar-right-start] {
  border-left: var(--bar-control-divider-strong);
  /* Replaces <div class="taskbar-spacer">. The renderer marks whichever control
   * opens the right group, so the grouping survives any slot being emptied. */
  margin-inline-start: auto;
}
/* First control overall never takes a leading divider, even if it opens the
 * right group because every left slot is empty. */
.shell-bar__scroll-lane > [data-taskbar-slot]:first-child {
  border-left: 0;
}

/* ---------- Slot G version control ----------
 * Keep six trailing identity characters visible even when the row compacts.
 * It participates in ordinary slot ordering and has no independent auto margin. */
.shell-bar > .shell-bar__build {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .3em;
  flex: 0 0 auto;
  min-inline-size: 7ch;
  max-inline-size: 17ch;
  overflow: hidden;
  padding-inline: .5em;
  font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .03em;
  color: inherit;
  white-space: nowrap;
  cursor: pointer;
}
.shell-bar__build-code { display: block; flex: 0 0 auto; white-space: nowrap; }
.shell-bar > .shell-bar__build { justify-content: flex-end; }
.shell-bar[data-compact="true"] > .shell-bar__build { inline-size: 8ch; }
.shell-bar > .shell-bar__build[data-build-state="stale"] { color: var(--bar-warn-fg); }
.shell-bar > .shell-bar__build:focus-visible { outline: var(--bar-control-outline); }
.shell-bar__build-age { font: inherit; }
.shell-version-details { max-inline-size: min(34rem, calc(100vw - 2rem)); overflow-wrap: anywhere; color: var(--of-ink); background: var(--of-paper); border: 1px solid currentColor; border-radius: .5rem; padding: 1.25rem; }
.shell-version-details::backdrop { background: var(--overlay-scrim); }
.shell-version-details button { min-block-size: 40px; margin-inline-end: .75rem; }
@media (max-width: 400px) { .shell-bar__build-age { display: none; } }

/* ---------- states ---------- */
.shell-bar :is(button, a, [role="button"]):hover,
.shell-bar :is(button, a, [role="button"]):focus-visible {
  background: var(--bar-control-bg-hover);
  outline: var(--bar-control-outline);
  outline-offset: var(--bar-control-outline-offset);
}
.shell-bar :is(button, a, [role="button"]):active,
.shell-bar :is(button, a, [role="button"])[aria-pressed="true"],
.shell-bar :is(button, a, [role="button"])[aria-current] {
  background: var(--bar-control-bg-active);
}
.shell-bar :is(button, a, [role="button"]):disabled,
.shell-bar :is(button, a, [role="button"])[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: .55;
}

/* NARROW WIDTHS: the words give way to icons.
 *
 * Owner: "we need when screen width comes in that the words are replaced by
 * icons and text size reduces."
 *
 * The type and padding half was ALREADY DONE and already committed - see the
 * --bar-* overrides in shell-tokens.css, which step down at 60rem and again at
 * 50rem and whose comment says "<= 50rem ICONS ONLY". The skin never implemented
 * the icons-only half, so the tokens described a state the CSS could not reach.
 * This is that half, on the boundary the tokens already declare; no new
 * breakpoint is introduced and no --bar-* is forked here, per this file's own
 * rule that a surface stylesheet must never fork a bar token.
 *
 * The label is CLIPPED, never `display: none`. The icon is aria-hidden, so
 * taking the label out of the box is fine but taking it out of the
 * accessibility tree would leave a button with no accessible name at exactly
 * the width where a screen reader is most likely to be in use.
 *
 * `overflow-x: auto` stays as the floor: if a module contributes enough
 * controls that even icons do not fit, order is preserved and the bar scrolls
 * rather than wrapping or truncating. */
/* The bar scrolls at ANY width. It used to scroll only below 50rem, on the
 * assumption that a narrow viewport is what makes a bar overflow. What
 * actually makes it overflow is how many controls the surface contributes:
 * the JSLC shell carries ten worded controls needing about 1100px and
 * overflowed at 1024, nowhere near the breakpoint. Order is preserved and
 * the scrollbar hidden - the contract calls that preserve-order-scroll. */
/* The renderer puts model controls other than Version into one lane. Version
 * remains the real G control beside it, so only the lane scrolls. */

/* A measured compact state lets a dense desktop bar use its declared icons
 * before it becomes a hidden horizontal strip. Controls without icons retain
 * their words: the renderer never turns a real action into a blank square. */
.shell-bar[data-compact="true"] > .shell-bar__scroll-lane > :is(button, a, [role="button"]):has(> :is(.btn-icon, .btn-emoji)) .btn-label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (width <= 50rem) {
  .shell-bar > .shell-bar__scroll-lane > :is(button, a, [role="button"]):has(> :is(.btn-icon, .btn-emoji)) .btn-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .shell-bar :is(button, a, [role="button"]) { transition: none; }
}

/* ---------- words to icons at narrow widths ----------------------------------
 * Owner request: "when screen width comes in that the words are replaced by
 * icons and text size reduces."
 *
 * A control authors BOTH forms: an icon span (`.btn-icon`, or `.btn-emoji` which
 * the Mainframe already used) and `.btn-label`. Wide, the bar shows words.
 * At <= 50rem it shows icons.
 *
 * The label is CLIPPED, never `display: none`. That is the Mainframe's own
 * technique and it is the better one: an icon-only bar still announces
 * "Navigation" to a screen reader, and the label contributes no width or gap
 * because it is taken out of flow. A control that ships no icon keeps its words
 * at every width - better a wide word than a blank square.
 *
 * Only BEHAVIOUR lives here. The type step and the control padding are token
 * values in shell-tokens.css, so no surface stylesheet forks a --bar-*. */
.btn-icon { display: inline-block; }
.btn-icon + .btn-label { margin-left: .35em; }
.shell-bar :is(.btn-icon, .btn-emoji) {
  align-items: center;
  justify-content: center;
  font-size: var(--bar-icon-size);
  line-height: 1;
  font-family: system-ui, "Segoe UI Emoji", "Segoe UI Symbol", "Apple Color Emoji", "Noto Color Emoji", sans-serif;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
.shell-bar .btn-icon { display: none; }
.shell-bar .btn-label { display: inline; }

@media (width <= 50rem) {
  .shell-bar .btn-icon { display: inline-flex; }
  .shell-bar :is(button, a, [role="button"]):has(> :is(.btn-icon, .btn-emoji)) .btn-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Measured compact mode also applies above the narrow-screen breakpoint. */
.shell-bar[data-compact="true"] .btn-icon { display: inline-flex; }

/* CIC-only floating presentation; assignment remains the existing Version control. */
#cic-floating-version { position:fixed; z-index:17; display:flex; align-items:center; gap:8px; max-width:calc(100vw - 8px); padding:3px 7px; background:var(--version-strip-surface); color:var(--version-strip-ink); border:1px solid var(--version-strip-border); border-radius:3px; font:11px/1.3 Arial,sans-serif; box-sizing:border-box; }
#cic-floating-version[hidden] { display:none; }
#cic-floating-version .shell-bar__build { background:transparent; border:0; padding:2px 0; color:inherit; font:600 11px/1.3 monospace; cursor:pointer; min-width:0; }
#cic-floating-version time { white-space:nowrap; }
#cic-floating-version .shell-bar__build:focus-visible { outline:2px solid var(--version-strip-ink); outline-offset:2px; }
