/* ============================================================================
   Mindprint — the header bar.

   The design system's header component (design-system/components/header-bar.html),
   ported once and shared by every surface that has a bar: the /admin area and the
   public shell alike. It lived inside admin.css until the pattern page needed it,
   which is exactly the moment a second copy would have been written.

   Consumes the canonical tokens from tokens.css; never redefines an --mp-* name.
   The .hbtn button system comes with it — the bar's controls are built from it,
   and it is the design system's pill, not an admin invention.

   Behaviour lives in js/header-bar.js: the bar measures its OWN width and sheds
   one control at a time, rather than switching at fixed device breakpoints.
   ========================================================================== */

:root {
  --admin-bar-h: 66px;
  /* The design system's button hover pair, needed by .hbtn below. admin.css
     defines these too, with the same values; both files must stand alone. */
  --admin-btn-hover: #26262C;
  --admin-edge: rgba(255, 255, 255, .30);
}

.bar {
  display: flex;
  align-items: center;
  gap: 20px;
  height: var(--admin-bar-h);
  padding: 0 22px;
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--mp-nav);
  border-bottom: 1px solid var(--mp-line);
}

.brand {
  display: flex;
  align-items: center;
  flex: none;
  margin-right: auto;
}

.brand img {
  height: 23px;
  width: auto;
  display: block;
}

.links {
  display: flex;
  align-items: center;
  gap: 28px;
  white-space: nowrap;
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 12px;
}

/* Direct children only: a grouped section's dropdown lives inside .links, and its options
   are .nav-opt rows — they must not inherit the row's own padding, colour or underline. */
.links > a {
  position: relative;
  color: var(--mp-dim);
  padding: 22px 0;
  line-height: 1;
  transition: color .15s;
}

.links > a:hover { color: var(--mp-ink); }
.links > a.on { color: var(--mp-ink); }

.links > a.on::after,
.links .group-trigger.on::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--mp-brand-grad);
}

/* A grouped section in the link row: the same link, wearing a chevron, opening the
   bar's own dropdown surface. Nine operator tools cost one slot in the row. */
.group-wrap { position: relative; display: inline-flex; flex: none; }

.group-trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 22px 0;
  background: none;
  border: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  line-height: 1;
  color: var(--mp-dim);
  cursor: pointer;
  transition: color .15s;
}

.group-trigger:hover { color: var(--mp-ink); }
.group-trigger.on { color: var(--mp-ink); }

/* Page-name dropdown — shown once the link row no longer fits. */
.section-wrap { position: relative; display: none; flex: none; }

.switch { gap: 10px; padding: 0 16px; }

.switch .lbl {
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 12px;
}

.switch .chev,
.group-trigger .chev,
.group-summary .chev {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
  transition: transform .18s;
}

.open > .switch .chev,
.open > .group-trigger .chev,
.nav-group[open] > .group-summary .chev { transform: rotate(180deg); }

/* Hamburger — always the right-most control. */
.burger-wrap { position: relative; display: none; flex: none; }

/* Shared dropdown surface. */
.menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 210px;
  z-index: 50;
  background: #141418;
  border: 1px solid var(--mp-line-soft);
  border-radius: 12px;
  padding: 8px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .55);
  display: none;
  max-height: calc(100vh - var(--admin-bar-h, 66px) - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Only the wrapper whose trigger was pressed opens. Keyed off the wrapper rather than a
   single flag on the bar, because the link row's group menu can be visible at the same
   collapse level as nothing else is — the old bar-wide flag revealed every .menu at once
   and was only ever correct while .section-wrap and .burger-wrap could not co-exist. */
.bar .open > .menu { display: block; }

.nav-opt {
  position: relative;
  display: block;
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 12px;
  color: var(--mp-dim);
  padding: 12px 12px 12px 28px;
  border-radius: 8px;
}

.nav-opt:hover { color: var(--mp-ink); background: var(--mp-raise); }
.nav-opt.on { color: var(--mp-ink); }

.nav-opt.on::before {
  content: "";
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  width: 6px;
  height: 6px;
  border-radius: var(--mp-r-pill);
  background: var(--mp-pink);
}

/* A grouped section inside a menu: the platform's own disclosure, open when the page you
   are on is inside it. Closed, the operator tools are one row rather than nine — which is
   the entire point of the group on a phone. */
.nav-group > .group-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: pointer;
  list-style: none;
}

.nav-group > .group-summary::-webkit-details-marker { display: none; }
.nav-group > .group-summary::marker { content: ""; }
.nav-group[open] > .group-summary { color: var(--mp-ink); }

/* The members sit under a hairline that reads as "these belong to the row above". */
.nav-group[open] > .nav-opt.sub {
  margin-left: 20px;
  padding-left: 20px;
  border-left: 1px solid var(--mp-line-soft);
  border-radius: 0 8px 8px 0;
}

.nav-group > .nav-opt.sub.on::before { left: 7px; }

.actions { display: flex; align-items: center; gap: 12px; flex: none; }

.vr {
  width: 1px;
  height: 26px;
  background: var(--mp-line);
  flex: none;
  margin: 0 2px;
}

/* The .hbtn button system, verbatim from the component. */
.hbtn {
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: var(--mp-r-pill);
  background: var(--mp-raise);
  border: 1px solid var(--mp-line-soft);
  color: var(--mp-dim);
  cursor: pointer;
  flex: none;
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 12px;
  font-weight: 400;
  transition: border-color .15s, color .15s, background .15s;
}

.hbtn:hover {
  color: var(--mp-ink);
  border-color: var(--admin-edge);
  background: var(--admin-btn-hover);
}

/* The design system's solid pink pill — the other half of the one button system, and therefore
   here rather than in storefront.css: the mini-cart carries it and renders on every page of the
   site, including the ones that never load the storefront sheet. */
.hbtn.primary {
  background: var(--mp-pink);
  color: var(--mp-ink-on-pink);
  border-color: transparent;
  font-weight: 700;
  height: 46px;
  padding: 0 26px;
  border-radius: var(--mp-r-pill);
}

.hbtn.primary:hover {
  background: var(--mp-pink-soft);
  color: var(--mp-ink-on-pink);
  border-color: transparent;
}

/* One disabled treatment for the whole system: dimmed, and the cursor says why you cannot press
   it. A control that is off must look off — a full-strength pink pill that does nothing reads as
   a broken page rather than as a state. */
.hbtn[disabled],
.hbtn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

.hbtn[disabled]:hover,
.hbtn[aria-disabled="true"]:hover {
  background: var(--mp-raise);
  border-color: var(--mp-line-soft);
  color: var(--mp-dim);
}

.hbtn.primary[disabled]:hover {
  background: var(--mp-pink);
  border-color: transparent;
  color: var(--mp-ink-on-pink);
}

.hbtn.icon { position: relative; width: 40px; padding: 0; }

.hbtn.icon svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The cart chip (design-system product-browser.html .cart): the icon circle with a count dot.
   A real link to /cart, which js/header-bar.js upgrades in place into a trigger for the bar's own
   dropdown — so the chip navigates with no script and opens the mini-cart with it. */
.cart-wrap { position: relative; display: inline-flex; flex: none; }

.hbtn.cart { border-radius: var(--mp-r-pill); }

/* An empty cart still carries the chip — it is how you find out it is empty — and drops the dot.
   The rule is needed because .dot sets `display: grid`, which outranks the UA's [hidden]. */
.hbtn.cart .dot[hidden] { display: none; }

.hbtn.cart .dot {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--mp-r-pill);
  background: var(--mp-pink);
  color: var(--mp-ink-on-pink);
  font-family: var(--mp-mono);
  font-weight: 700;
  font-size: 10px;
  line-height: 1;
  display: grid;
  place-items: center;
  border: 2px solid var(--mp-nav);
}

/* ── The mini-cart ──────────────────────────────────────────────────────────────────────────
   The bar's own .menu surface with a body instead of a list of links: same box, same shadow,
   same open/close, so there is exactly one dropdown mechanism on this header. Its contents are
   a server-rendered fragment (/cart?handler=Mini), fetched on first open.

   Wider than a nav menu because it carries thumbnails and money, and capped against the viewport
   so the narrowest bar the design supports still shows the whole panel. */
.menu.mini-cart {
  padding: 14px;
  cursor: default;
}

/* Hung from the chip's right edge, a 330px panel runs off the side of the screen — and *which*
   side, and at what width, depends on where the chip has been pushed to, not on the viewport.
   This was first written as a `max-width: 420px` breakpoint on the theory that the chip is "near
   the right margin"; it is not. Once the bar carries Account, the environment badge and the
   hamburger to the chip's right, the chip sits mid-bar, and the panel hangs off the LEFT edge at
   widths the breakpoint never covered. Roger caught it at ~555px.

   A fixed breakpoint was the wrong instrument anyway: this bar's whole doctrine is that it
   measures itself rather than guessing from device widths (see js/header-bar.js). So the panel is
   placed by measurement too — js/header-bar.js sets --mini-left and --mini-w from the chip's real
   position, clamped so the panel is always fully on screen, and re-measures on resize while open.
   The declarations below are what a panel gets before the first measurement and if the custom
   properties are ever absent: a viewport-anchored panel, correct at any width, never clipped.

   Fixed rather than absolute because the bar is sticky, and sticky is not a containing block for a
   fixed child — the panel measures against the viewport, which is exactly the box it must fit in. */
.menu.mini-cart {
  position: fixed;
  top: var(--mini-top, calc(var(--admin-bar-h, 66px) + 8px));
  left: var(--mini-left, auto);
  right: var(--mini-right, 10px);
  width: var(--mini-w, min(330px, calc(100vw - 20px)));
  max-height: var(--mini-max-h, calc(100vh - var(--admin-bar-h, 66px) - 24px));
  overflow-y: auto;
  overscroll-behavior: contain;
}

.mini-cart .mini-wait,
.mini-cart .mini-empty {
  margin: 0;
  padding: 14px 4px;
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 10px;
  line-height: 2;
  color: var(--mp-mute);
  text-align: center;
}

.mini-cart .mini-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 10px;
  color: var(--mp-mute);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--mp-line);
}

.mini-cart .mini-head b { color: var(--mp-dim); font-weight: 400; }

.mini-cart .mini-list { display: flex; flex-direction: column; }

.mini-cart .mini-line {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--mp-line);
}

.mini-cart .mini-line.is-blocked { opacity: .55; }

.mini-cart .mini-art {
  position: relative;
  width: 40px;
  aspect-ratio: 4 / 4.6;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--mp-line);
  background: linear-gradient(180deg, #0C0C10, #08080A);
}

.mini-cart .mini-art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 8%;
}

/* ── The unrendered cell (D59), base rule ────────────────────────────────────────────────────
   A garment we have not yet rendered this pattern on shows the blank plate — a transparent
   provider cut-out — over the pattern itself, so the cell reads as "this product, this print, not
   photographed together yet" rather than as a picture of a different product. `.is-unrendered`
   goes on the image well and the pattern arrives as --mp-behind on the same element; without the
   variable it degrades to the plain plate, which is what the old behaviour was.

   It lives in THIS sheet, not in storefront.css where the rest of the card pane is, for the same
   reason .hbtn.primary does: the mini-cart marks its thumbs up this way and the mini-cart renders
   on every page of the site — /generate, /, /p/ and all of /admin never load the storefront sheet.
   With the rule over there the same cart line showed the pattern behind the plate on /patterns and
   a bare plate on a dark gradient on /generate: no pattern, no badge, no D59 signal at all.

   storefront.css keeps what only its own components have: the pane and mat variants of ::before,
   and the "NOT YET RENDERED" badge. */
.is-unrendered { position: relative; isolation: isolate; }

.is-unrendered::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--mp-behind, none);
  background-size: 38% auto;
  background-repeat: repeat;
  opacity: .32;
  z-index: 0;
}

.is-unrendered > img,
.is-unrendered > span { position: relative; z-index: 1; }

/* The badge the card pane hangs on an unrendered cell is eight pixels of monospace; at 40px wide
   it would be a smudge. The thumb keeps the plate-over-pattern treatment and says it in the
   tooltip instead — the page beside it carries the words. */
.mini-cart .mini-art.is-unrendered::after { content: none; }

/* No imagery at all — the storefront's "nothing here yet" diagonal, so an empty thumb reads as a
   missing photograph rather than as a hole in the panel. */
.mini-cart .mini-art:empty {
  background-color: #1B1B1F;
  background-image: repeating-linear-gradient(45deg, #1B1B1F 0 8px, #212127 8px 16px);
}

.mini-cart .mini-mid { min-width: 0; display: flex; flex-direction: column; gap: 3px; }

.mini-cart .mini-nm {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--mp-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mini-cart .mini-sub {
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: 9px;
  color: var(--mp-mute);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mini-cart .mini-sub.is-why { color: var(--mp-peach); }

.mini-cart .mini-amt {
  font-family: var(--mp-mono);
  font-weight: 700;
  font-size: 12px;
  color: var(--mp-pink);
  white-space: nowrap;
}

.mini-cart .mini-more {
  display: block;
  padding: 10px 0 0;
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 9.5px;
  color: var(--mp-mute);
  text-align: center;
}

.mini-cart .mini-sum {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 0 2px;
}

.mini-cart .mini-sum .l {
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 10px;
  color: var(--mp-dim);
}

.mini-cart .mini-sum .v {
  font-family: var(--mp-mono);
  font-weight: 700;
  font-size: 16px;
  color: var(--mp-pink);
}

.mini-cart .mini-acts { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }

.mini-cart .mini-acts .hbtn { width: 100%; height: 40px; }

/* The favorite pill (design-system buttons.html): a ghost secondary whose ♥ is the accent.
   Pressed is a held state, not a hover — the border takes the pink so the pill reads as "on"
   at rest. Lives here because .hbtn is the one button system and .fav is one of its words. */
.hbtn.fav .heart { color: var(--mp-pink); font-size: 14px; line-height: 1; }

.hbtn.fav { padding: 0 18px; }

.hbtn.fav[aria-pressed="true"] {
  color: var(--mp-ink);
  border-color: var(--mp-pink);
}

.fav-hint {
  font-family: var(--mp-mono);
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: 10px;
  color: var(--mp-mute);
  margin-right: 10px;
}

/* Icon-only, for corners: the 40px circle the button system already speaks. */
.hbtn.fav.fav-compact { width: 40px; padding: 0; border-radius: var(--mp-r-pill); }

/* The environment marker, in the same pill language as .hbtn. */
.env {
  height: 26px;
  padding: 0 11px;
  border-radius: var(--mp-r-pill);
  background: rgba(255, 201, 160, .12);
  border: 1px solid rgba(255, 201, 160, .28);
  color: var(--mp-peach);
  font-family: var(--mp-mono);
  font-weight: 700;
  font-size: 9.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  flex: none;
}

/* The bar's one optional action, in .hbtn's own language. Its menu copy is the
   component's `.m-signin` slot: present in the markup, revealed only once the
   bar sheds it. */
.bar-action { padding: 0 18px; white-space: nowrap; }

.menu .m-action {
  display: none;
  width: calc(100% - 8px);
  height: 44px;
  margin: 12px 4px 4px;
}

/* The collapsed bar's search box, verbatim from the component's `.m-search` slot: present in the
   markup of every bar that offers search, revealed only once the magnifier itself is shed. It is
   a real GET form, so the narrowest bar still searches with no script running. */
.menu .m-search {
  display: none;
  align-items: center;
  gap: 10px;
  height: 42px;
  padding: 0 16px;
  margin: 2px 4px 8px;
  background: var(--mp-raise);
  border: 1px solid var(--mp-line-soft);
  border-radius: var(--mp-r-pill);
  color: var(--mp-mute);
}

.menu .m-search svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  flex: none;
}

.menu .m-search input {
  flex: 1;
  min-width: 0;
  background: none;
  border: 0;
  outline: none;
  color: var(--mp-ink);
  font-family: var(--mp-mono);
  font-size: 13px;
}

.menu .m-search input::placeholder { color: var(--mp-mute); }

/* ── Progressive collapse — each step sheds one control and keeps it
      reachable inside the menu. Driven by js/header-bar.js measuring the bar.

   The design system's own shed order (components/header-bar.html) is:
   links → page-name dropdown → Sign-in icon → hamburger → Sign in into menu → SEARCH LAST,
   because search is the most valuable control on the bar and the last thing worth losing.

   Ours is that order with two honest differences, rather than a renumbering of it:

     c1  links → page-name dropdown                      (the design's c1)
     c2  unused, and reserved                            (the design's c2)
     c3  page-name dropdown → hamburger                  (the design's c3)
     c4  the bar's one action → the hamburger menu       (the design's c4)
     c5  the environment badge hides                     (OURS — the design has no badge)
     c6  the search control → .m-search in the menu      (the design's c5, kept last)

   c2 stays empty because the design sheds a *Sign in pill* to a person glyph there, and our
   action slot carries an arbitrary label ("Account", "Back") that no single icon can stand for.
   Shedding nothing at that step costs one no-op class and keeps every other number meaning what
   the design says it means; overloading it with something else would not.

   c5 keeps its own meaning and its own number: an operator's environment marker is chrome, and
   chrome goes before a control. Search therefore lands at c6, still last, which is the property
   the design's ladder was actually asserting. The brand and the cart never shed, in either. ── */
.bar.c1 .links { display: none; }
.bar.c1 .section-wrap { display: inline-flex; }
.bar.c3 .section-wrap { display: none; }
.bar.c3 .burger-wrap { display: inline-flex; }
/* c4 — the action folds into the hamburger, exactly as the component folds Sign in. */
.bar.c4 .actions .bar-action { display: none; }
.bar.c4 .menu .m-action { display: inline-flex; }
.bar.c5 .env { display: none; }
/* c6 — the magnifier leaves the bar and becomes the menu's search field. */
.bar.c6 .actions .search-btn { display: none; }
.bar.c6 .menu .m-search { display: flex; }

/* ── The floor ──────────────────────────────────────────────────────────────────────────────
   Below this the bar has three things it may never shed — the brand, the cart and the way into
   the menu — and at the desktop's metrics they do not fit: at 240px the wordmark alone is 126px
   of a 240px bar, and the row overflowed its own box by 45px once the cart chip went site-wide.

   Nothing is dropped here, because the ladder above has already dropped everything it is allowed
   to. What gives is measurement: the page padding, the gaps and the wordmark tighten, and the
   hairline between the brand and the actions goes, which is chrome separating a row of links that
   is no longer there. Measured at 240px — the narrowest width this bar is asked to survive. ── */
@media (max-width: 380px) {
  .bar { padding: 0 12px; gap: 10px; }
  .bar .brand img { height: 20px; }
  .actions { gap: 10px; }
  .actions .vr { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .switch .chev { transition: none; }
}
