/* Symbulator — the shared banner
   ==========================================================================
   ONE source for the lockup that appears on all three properties:

       symbulator.com          Documentation/landing/
       learn.symbulator.com    Documentation/web/  (via build.py)
       the app                 repos/local, repos/server

   This file exists because the same rules were previously written out three
   times in three repositories, and drifted twice in a single day, in both
   directions, each fix a person copying values by hand. Import it; do not
   copy it.

   Two bands: .topbar carries the lockup alone, .subbar carries each
   property's own controls in a slightly lighter shade. The sky keyline
   closes the pair, under the subbar.

   It is self-contained on purpose. Every colour is var(--name, #literal), so
   it works whether or not the host defines the tokens, and whatever the host
   calls them.

   Scope widened 23 Aug 2026. It used to style the bands and nothing inside
   them, leaving every property to dress its own ribbon -- which produced
   three ribbons that looked like three different websites. It now also
   owns the ribbon's shared vocabulary: the row, and what a link in it looks
   like. What goes *in* the row is still each property's own business, and
   genuinely local controls (learn's version picker, the app's Clear all
   inputs) still layer on top in their own stylesheets.

   Both .vnum and .tm are matched for the version numeral, because the three
   properties named that span differently before this file existed.

   Verified computed values at 1280px wide: lockup band 148px, controls
   ribbon 62px, container 1152 and left edge 64 on both,
   logo 80/r12, gap 19.2px, name 32/700/.5px/lh49.6, numeral italic 29.44px
   #8ec7f5, second line 16px #b7c3d6, keyline 3px. If you change anything
   here, re-measure — do not judge by eye.
   ========================================================================== */

:root {
  --banner-w:   72rem;
  --banner-pad: clamp(1.25rem, 4vw, 2.75rem);
}

.topbar {
  position: relative; z-index: 50;
  padding-block: 2.2rem 2rem;
  background: var(--navy, #203864);
  color: #fff;
}

/* The controls ribbon: a second, slightly lighter band under the lockup.
   The lockup band carries the identity and nothing else; every control --
   nav links on symbulator.com, Start reading / Download the PDF and the
   version picker on learn, whatever the app puts there -- sits down here.

   The two bands are one assembly: the shade change is the only divider
   between them, and the 3px sky keyline finishes the pair rather than
   splitting them, so it moved off .topbar and onto .subbar. A page with no
   subbar keeps the keyline via .topbar:last-child below.

   #2a4576 is --navy lightened about 8% -- far enough to read as a distinct
   band on both themes, close enough that the two still read as one header.
   Deliberately not a token: it exists only in relation to --navy. */
.subbar {
  /* Above .topbar so the version picker's dropdown, which lives inside this
     band, is never trapped under the lockup's stacking context. */
  position: relative; z-index: 51;
  background: var(--navy-2, #2a4576);
  border-bottom: 3px solid var(--sky, #8ec7f5);
  color: #fff;
}
.subbar-inner {
  width: min(var(--banner-w), 100%); margin-inline: auto;
  padding-inline: var(--banner-pad);
  min-height: 3.25rem;
  display: flex; align-items: center; gap: 0.6rem;
  flex-wrap: wrap;
  padding-block: 0.6rem;
}
/* Controls sit left, under the wordmark; anything after .subbar-spacer is
   pushed to the right edge. */
.subbar-spacer { flex: 1 1 auto; }

/* The ribbon's links, shared by all three properties.
   ---------------------------------------------------------------------
   These moved here on 23 Aug 2026. Until then this file styled the bands
   and nothing inside them, on the principle that each property owns its
   own controls -- and the result was three ribbons that read as three
   different websites: symbulator.com had plain links, learn had two solid
   chips, the app had no ribbon at all.

   The lesson is the same one the lockup taught. A shared band with
   unshared contents is not a shared banner. So the *vocabulary* lives
   here -- a row of links, and what a link in a navy ribbon looks like --
   while what each property puts in the row stays its own business.

   Anything genuinely local still layers on top: learn's version picker,
   the app's Clear all inputs. They sit in the same row, at the same
   size. */
.subbar nav {
  display: flex; align-items: center; gap: 1.15rem;
  flex-wrap: wrap; min-width: 0;
  /* flex-basis 0, so the nav never makes the ribbon two rows (#143).
     Flexbox wraps a row by hypothetical (content) sizes before it
     shrinks anything, so with basis auto a crowded learn ribbon dropped
     its version picker to a second line while the nav still showed all
     its links -- and the one-line clip below never got its chance. At
     basis 0 the nav claims no width of its own, growing into what the
     row can spare, and a link that does not fit wraps inside the nav and
     is clipped. The row itself stays one line at every width.

     Grow 999, not 1: .subbar-spacer grows too, and at equal factors it
     took half the free space and starved the nav into clipping links it
     had room for (measured at 375px on the landing page). At 999 the
     nav takes what the row can spare and its own empty tail does the
     spacer's job; the spacer stays for rows that have no nav. */
  flex: 999 1 0;
  /* One row of links, never two (Roberto, 28 Aug 2026: a link that would
     wrap should hide instead). The row still flex-wraps, but the box is
     capped at one line-box (0.875rem x 1.4, the size every link in it is
     pinned to below) and clipped, so anything that wrapped is simply not
     shown -- at any width, no media query to keep in step with the labels.
     The padding is not rhythm: focus rings sit 3px off a link and 2px
     wide, and without the 0.375rem of breathing room the clip would shave
     them. box-sizing is pinned because the cap must mean the same thing on
     a host that sets border-box (learn, the landing) and one that does not.
     overflow is clip, not hidden, so keyboard focus on a hidden link
     cannot scroll the row into a half-shown state. */
  box-sizing: content-box;
  padding-block: 0.375rem;
  max-height: calc(0.875rem * 1.4);
  overflow: clip;
}
.subbar nav a {
  /* font-family is pinned, not inherited. learn.symbulator.com sets its
     body in IBM Plex Serif for long-form reading, so an inheriting ribbon
     rendered its links in a serif there and in a sans on the other two --
     the same words, three sizes of the same idea, in two different faces.
     Reported 24 Aug 2026. --sans is whatever the host calls its sans stack;
     the literal is here for a host that defines nothing. */
  font-family: var(--sans, -apple-system, "Segoe UI", Roboto, Helvetica,
                Arial, sans-serif);
  color: #dbe6f5; text-decoration: none;
  font-size: 0.875rem; line-height: 1.4;
  border-radius: 4px;
}
.subbar nav a:hover { color: #fff; text-decoration: underline; }
.subbar nav a:focus-visible {
  outline: 2px solid var(--sky, #8ec7f5); outline-offset: 3px;
}
/* A link that happens to act on the page rather than lead somewhere -- the
   app's Clear all inputs. Same size and colour as its neighbours; it is a
   <button> only because it does something, and should not look like one.

   The class is .subbar-action, not the more natural .linkish, because the
   app already has a small underlined link-button of its own under that very
   name -- and the two collided: this rule won on specificity for what it
   declared, and the app's underline came through for what it did not, so
   Clear all inputs rendered underlined at rest while its neighbours did not.
   A shared file must not claim a class name a host might already use. Check
   for collisions before naming anything here.

   The selector is .subbar, not .subbar nav: an action may sit after
   .subbar-spacer, at the right-hand end beside the theme toggle, which
   puts it outside <nav>. The app's "Clear all inputs" does exactly that.
   Adding nav back would silently strip the styling off any such button. */
.subbar button.subbar-action {
  appearance: none; background: none; border: 0; padding: 0;
  font-family: var(--sans, -apple-system, "Segoe UI", Roboto, Helvetica,
                Arial, sans-serif);
  font-weight: 400; color: #dbe6f5; font-size: 0.875rem; line-height: 1.4;
  cursor: pointer; border-radius: 4px;
}
.subbar button.subbar-action:hover { color: #fff; text-decoration: underline; }
.subbar button.subbar-action:focus-visible {
  outline: 2px solid var(--sky, #8ec7f5); outline-offset: 3px;
}
.subbar button.subbar-action:disabled {
  color: #8ea3c4; cursor: default; text-decoration: none;
}

/* Short spellings for a crowded ribbon (#144, #145, Roberto's brief of
   29 Aug 2026): a ribbon control may carry two labels --

     <a href="...">Documentation<span class="subbar-lbl-short">Docs</span>
     </a>  is wrong; the pair is two spans:
     <span class="subbar-lbl">Documentation</span>
     <span class="subbar-lbl-short">Docs</span>

   -- and the ribbon shows exactly one: the full spelling above 480px,
   the short one at or below, where the phone-width media queries
   already move the property mark and hide the subtitle. The app says
   App / Docs / Clear inputs there; the Numerical Solver says Docs.
   Same two-spellings idea as the property mark and learn's version
   key, shared here so every property abbreviates at the same width. */
.subbar .subbar-lbl-short { display: none; }
@media (max-width: 480px) {
  .subbar .subbar-lbl { display: none; }
  .subbar .subbar-lbl-short { display: inline; }
}

/* The property mark (#135, Roberto's brief of 28 Aug 2026): which of
   the properties the reader is on, said once and quietly -- spaced
   capitals in the sky at 55%, the app's [ T O O L S ] motif moved into
   the banner. The styling is shared vocabulary here; each property
   supplies its own word (Documentation, Welcome, Application,
   Numerical), and the app's is wrapped in the template markers that
   the offline build strips, so the downloaded copy stays unmarked,
   per the brief. (Named indirectly here on purpose: build_local
   counts the literal marker token in its output as proof none
   survived the strip, and a stylesheet comment must not trip it.)

   One mark, two spellings in the markup, exactly one ever shown
   (treatment 2 of the mockup Roberto chose): .property-mark-top sits
   at the right of the top band, a flex sibling of .header-brand
   inside .topbar-inner, full size above 640px and shrunk below;
   .property-mark-slot sits under the wordmark inside the lockup and
   takes over at <=480px, where the subtitle has hidden (see below)
   and left it the room. The negative right margin on the top form
   swallows the last letter's trailing letter-space, so the mark ends
   on the band's own right edge. */
.property-mark {
  /* the system stack, pinned like the lockup's own -- see .header-brand */
  font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.38em; text-transform: uppercase;
  color: var(--sky, #8ec7f5); opacity: 0.55;
  white-space: nowrap;
}
.property-mark-top { align-self: center; flex: none; margin-right: -0.38em; }
.property-mark-slot { display: none; margin: 0.3rem 0 0; }
@media (max-width: 640px) {
  .property-mark-top {
    font-size: 0.58rem; letter-spacing: 0.3em; margin-right: -0.3em;
  }
}
@media (max-width: 480px) {
  .property-mark-top { display: none; }
  .property-mark-slot {
    display: block; font-size: 0.58rem; letter-spacing: 0.3em;
  }
}

/* A header with no controls ribbon still needs its bottom edge. */
.topbar:last-child { border-bottom: 3px solid var(--sky, #8ec7f5); }

.topbar-inner {
  width: min(var(--banner-w), 100%); margin-inline: auto;
  padding-inline: var(--banner-pad);
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
}

.header-brand {
  /* The app loads no webfont. The websites load IBM Plex. Naming Plex here
     would render the banner in Plex on the sites and the system face in the
     app -- identical layout, different letterforms, and invisible unless you
     look closely. All three therefore pin the system stack on the banner
     alone; the page body keeps whatever the host uses. Do not "tidy" this
     back to --sans. */
  --banner-sans: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  display: flex; align-items: center; gap: 1.2rem;
  color: #fff; text-decoration: none; min-width: 0;
}
.header-logo { width: 80px; height: 80px; border-radius: 12px; flex: none; display: block; }

/* The scorpion is a link home, on every property and from every page.
   ---------------------------------------------------------------------
   It has to be its own anchor rather than part of .header-brand, because
   two of the three properties wrapped the whole lockup in a link already
   and an anchor inside an anchor is not valid markup. So .header-brand is
   a plain container now, and its children carry the links.

   Requested 24 Aug 2026: wherever you are -- reading a lesson, running the
   app offline -- the scorpion goes to symbulator.com. */
.header-logo-link {
  flex: none; display: block; border-radius: 12px;
  color: inherit; text-decoration: none;
}
.header-logo-link:focus-visible {
  outline: 2px solid var(--sky, #8ec7f5); outline-offset: 3px;
}
/* .header-brand may be a div wrapping links, or a link itself. Either way
   nothing inside it should look like an underlined blue anchor. */
.header-brand a { color: inherit; text-decoration: none; }
.header-title { min-width: 0; }

.brand-name {
  margin: 0; font-family: var(--banner-sans);
  font-size: 2rem; font-weight: 700; letter-spacing: 0.5px; line-height: 1.55;
}
.brand-name .vnum,
.brand-name .tm {
  color: var(--sky, #8ec7f5);
  font-family: Georgia, "Times New Roman", "Nimbus Roman", serif;
  font-style: italic; font-size: 0.92em; letter-spacing: 0;
}
/* The beta mark, set shorter than the numeral it follows (Roberto,
   3 Sep 2026: about 80% of its height). Georgia's beta has a long
   descender and an ascender taller than the digits, so at the numeral's
   own size it is the tallest thing in the lockup -- which is the wrong
   emphasis for a temporary mark. Inherits everything else, so it stays
   the same colour, face and slant.

   Both consumers that draw a beta carry the span: the app's wordmark and
   the landing page's. #137 removes the mark when 9 leaves beta, and this
   rule goes with it. */
.brand-name .tm .beta { font-size: 0.8em; }
.brand-sub {
  margin: 0.4rem 0 0; font-family: var(--banner-sans);
  font-size: 1rem; line-height: 1.55; color: #b7c3d6;
}

.theme-toggle {
  /* padding:0 is load-bearing, not tidiness. A host with a generic
     `button { padding: .6rem 1.6rem }` rule -- the app has exactly that --
     wins over the width below, because a flex item cannot shrink under its
     own padding. The toggle then measures 53x40 there and 40x40 on the
     websites: the same circle on two sites and an oval on the third.
     Measured 23 Aug 2026. */
  padding: 0;
  flex: none; width: 2.5rem; height: 2.5rem;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.12); color: #fff;
  border: 1px solid rgba(255,255,255,.35); border-radius: 999px;
  font-size: 1.2rem; line-height: 1; cursor: pointer;
  transition: background-color .15s ease, transform .06s ease;
}
.theme-toggle svg { width: 1.15em; height: 1.15em; flex: none; }
.theme-toggle:hover  { background: rgba(255,255,255,.22); }
.theme-toggle:active { transform: translateY(1px); }
.theme-toggle:focus-visible { outline: 2px solid var(--sky, #8ec7f5); outline-offset: 2px; }

@media (max-width: 520px) {
  .topbar { padding-block: 1.6rem 1.4rem; }
  .subbar-inner { min-height: 0; padding-block: 0.5rem; gap: 0.45rem; }
  .topbar-inner { gap: 0.9rem; }
  .header-brand { gap: 0.9rem; }
  .header-logo { width: 56px; height: 56px; border-radius: 9px; }
  .brand-name { font-size: 1.4rem; letter-spacing: 0.3px; }
  .brand-sub { font-size: 0.9rem; margin-top: 0.25rem; }
  .theme-toggle { width: 2.15rem; height: 2.15rem; font-size: 1.05rem; }
}

/* The second line hides before it wraps (Roberto, 28 Aug 2026: one line or
   none). Measured 28 Aug 2026 on the docs preview, Chrome on Windows: at
   this block's sizes the line holds to 450px of viewport and wraps by 440.
   480 leaves ~35px for wider system faces -- the stack above resolves to
   Roboto on Android and SF on iOS, neither of which was the one measured.
   If the subtitle's wording or any width in the 520px block above changes,
   re-measure; do not trust 480 across such a change. */
@media (max-width: 480px) {
  .brand-sub { display: none; }
}
