/* ==========================================================================
   RESPONSIVE — the mobile and tablet pass.

   Loaded last, so everything here is a deliberate override of the desktop
   rules rather than something tangled through them. Nothing below changes
   behaviour, only layout and size.

   Two ideas run through it:

   1. TOUCH TARGETS. Anything tappable gets at least 44px of height on a touch
      screen. The rules are gated on `(pointer: coarse)` as well as width, so a
      phone in landscape and a tablet both qualify, while a mouse user keeps
      the tighter editorial density the design was drawn at.

   2. ONE COLUMN. Every multi-column arrangement collapses to a vertical list
      at small widths, including the admin order table, which becomes a stack
      of labelled cards rather than a spreadsheet scrolling in a 330px window.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. STRUCTURE — spacing that scales with the viewport rather than jumping
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {
  :root {
    /* Tighter page inset: on a 375px screen, 4.5rem of gutter is a third of
       the screen spent on nothing. */
    --gutter: 1.25rem;
    --section-y: 3.5rem;
    --nav-h: 60px;
  }
}

@media (min-width: 701px) and (max-width: 1024px) {
  :root {
    --gutter: 2.25rem;
    --section-y: 5rem;
  }
}

/* --------------------------------------------------------------------------
   2. NAVIGATION — hamburger and slide-out
   -------------------------------------------------------------------------- */
.nav__end {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

/* The button exists only on touch/narrow layouts. */
.nav__burger { display: none; }

.nav__burger-bars,
.nav__burger-bars::before,
.nav__burger-bars::after {
  display: block;
  width: 20px;
  height: var(--rule-width);
  background: currentColor;
  transition: transform var(--dur-base) var(--ease),
              opacity var(--dur-fast) var(--ease);
}

.nav__burger-bars::before,
.nav__burger-bars::after {
  content: "";
  position: absolute;
}

.nav__burger-bars::before { transform: translateY(-6px); }
.nav__burger-bars::after  { transform: translateY(6px); }

/* Open: the three bars become a cross. */
.nav__burger[aria-expanded="true"] .nav__burger-bars { background: transparent; }
.nav__burger[aria-expanded="true"] .nav__burger-bars::before { transform: rotate(45deg); }
.nav__burger[aria-expanded="true"] .nav__burger-bars::after  { transform: rotate(-45deg); }

@media (max-width: 900px) {
  /* An element with backdrop-filter becomes the containing block for its
     fixed-position descendants. With it on, the slide-out's `bottom: 0`
     resolved against the 60px bar instead of the viewport and the panel was
     clipped to 88px tall — three of its four links simply gone. On a pitch
     black bar the blur was invisible anyway, and it costs GPU on a phone. */
  .nav {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: var(--bg);
  }

  .nav.is-stuck { background: var(--bg); }

  .nav__inner {
    /* Brand left, cart and burger right. The links leave the bar entirely. */
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .nav__burger {
    position: relative;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    color: var(--text-muted);
    transition: color var(--dur-fast) var(--ease);
  }

  .nav__burger:hover { color: var(--text); }

  /* The slide-out itself. Sits under the bar so the brand and the close
     control stay visible and reachable while it is open. */
  .nav__menu {
    position: fixed;
    top: var(--nav-h);
    right: 0;
    bottom: 0;
    z-index: 2;
    width: min(320px, 82vw);
    padding: var(--sp-5) var(--sp-5) var(--sp-8);
    background: var(--bg);
    border-left: var(--rule-strong);
    transform: translateX(101%);
    transition: transform var(--dur-slow) var(--ease);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .nav__menu.is-open { transform: translateX(0); }

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

  /* Dimming the page behind it, so the panel reads as a layer. */
  .nav__scrim {
    position: fixed;
    top: var(--nav-h);
    inset-inline: 0;
    bottom: 0;
    z-index: 1;
    background: rgba(0, 0, 0, 0.72);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-base) var(--ease);
  }

  .nav__scrim.is-open { opacity: 1; pointer-events: auto; }

  .nav__links {
    flex-direction: column;
    align-items: stretch;
    gap: 0;

    /* The bar centres this list with `justify-self: center`. Box Alignment
       applies justify-self to block-level boxes too, and any value other than
       normal/stretch shrink-wraps the box — so inside the slide-out the list
       collapsed to the width of the word "Store" and sat marooned in the
       middle of a 295px panel: 61px of tappable row out of 247px available,
       with separator rules to match. Undone here, in the one place the list
       is a column rather than a row. */
    justify-self: stretch;
    width: 100%;
  }

  /* Full-width rows, each its own hairline-separated line. */
  .nav__link {
    display: flex;
    align-items: center;
    min-height: 52px;
    padding-block: 0;
    border-bottom: var(--rule);
    font-size: var(--fs-small);
    letter-spacing: var(--tr-label);
  }

  .nav__link::after { display: none; }
  .nav__link[aria-current="page"] { color: var(--text); }

  .nav__link[aria-current="page"]::before {
    content: "";
    width: 5px;
    height: 5px;
    margin-right: 10px;
    background: var(--c-porcelain);
    border-radius: 50%;
  }

  .nav__brand-sub { display: none; }
}

/* --------------------------------------------------------------------------
   3. TOUCH TARGETS — 44px minimum wherever a finger lands
   -------------------------------------------------------------------------- */
@media (max-width: 900px), (pointer: coarse) {

  .nav__cart {
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
  }

  .drawer__close,
  .detail__close {
    width: 44px;
    height: 44px;
  }

  /* Quantity steppers: the single most-tapped control in the bag. */
  .stepper__btn {
    width: 44px;
    height: 44px;
    font-size: 15px;
  }

  .stepper__value {
    min-width: 44px;
    font-size: var(--fs-body);
  }

  /* "Remove" was an 18px-tall text link — impossible to hit cleanly. */
  .bag-item__remove,
  .promo__remove,
  .summary-block__edit,
  .stock-row__reset,
  .row-link,
  .confirm__copy,
  .footer__link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .pill {
    min-height: 44px;
    padding-inline: 1.15rem;
  }

  .promo__input,
  .promo__apply {
    min-height: 48px;
  }

  .card__action,
  .rec__add,
  .tabs__tab {
    min-height: 48px;
  }

  .field__input,
  .stock-field__input,
  .status-select {
    min-height: 48px;
  }

  /* 16px stops iOS Safari zooming the page when a field takes focus. */
  .field__input,
  .promo__input,
  .stock-field__input {
    font-size: 16px;
  }

  .btn {
    min-height: 48px;
    --btn-pad-y: 0.95rem;
  }

  .promo-row__toggle,
  .switch__option,
  .rec__open {
    min-height: 44px;
  }

  /* The move arrows get the full target even though it makes the column
     tall. They sit one directly above the other, and a mis-tap here silently
     reorders the storefront — the one control on this screen where being
     generous is worth the height it costs. */
  .rank { width: 74px; }
  .rank__btn { width: 44px; height: 44px; }
  .rank__btn svg { width: 12px; height: 8px; }

  /* Both halves of the visibility switch, not just the row it sits in. */
  .switch__option { display: inline-flex; align-items: center; }

  .skip-link { min-height: 44px; }
}

/* --------------------------------------------------------------------------
   4. STOREFRONT
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .hero__inner { min-height: auto; padding-block: var(--sp-8) var(--sp-7); }

  .hero__eyebrow { margin-bottom: var(--sp-5); }
  .hero__eyebrow::after { display: none; }

  .hero__headline { max-width: none; }

  .hero__body { margin-top: var(--sp-6); padding-top: var(--sp-5); gap: var(--sp-5); }
  .hero__actions { flex-direction: column; align-items: stretch; gap: var(--sp-4); }
  .hero__actions .btn { justify-content: space-between; }
  .hero__note { text-align: center; }

  .catalog__head { gap: var(--sp-3); }

  /* Let the filter row scroll sideways rather than wrap into three ragged
     lines and push the grid down the page. */
  .catalog__filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: var(--sp-2);
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
  }

  .catalog__filters::-webkit-scrollbar { display: none; }
  .pill { flex: none; }

  .standards__item { padding-block: var(--sp-6); }

  /* Product cards: the two actions stack.
     Side by side they are a `1fr auto` grid, so "View Details" takes the width
     it needs and "Add to Cart" lives on the remainder. At 320px that remainder
     comes to 82px for 82px of text — the button is exactly its own label with
     nothing to spare, and one longer word would clip it. Stacked, each action
     is a full-width row with the same hairline between them that the column
     rule provided. */
  .card__actions { grid-template-columns: minmax(0, 1fr); }

  .card__action--details {
    border-left: 0;
    border-top: var(--rule);
  }

  .footer__inner { flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
  .footer__links { gap: var(--sp-4) var(--sp-5); }
}

/* --------------------------------------------------------------------------
   5. BAG, CHECKOUT, PRODUCT DETAIL
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .drawer__panel { width: 100%; border-left: 0; }

  .drawer__head { padding-inline: var(--gutter); }
  .bag-item { padding-inline: var(--gutter); }
  .drawer__foot { padding-inline: var(--gutter); }
  .drawer__empty { padding-inline: var(--gutter); }

  /* Thumbnail, then everything else full width beneath the title. */
  .bag-item { grid-template-columns: 56px minmax(0, 1fr); }
  .bag-item__image { width: 56px; height: 70px; }

  .bag-item__total {
    grid-column: 2;
    grid-row: 2;
    margin-top: var(--sp-2);
    font-size: var(--fs-body);
  }

  .bag-item__controls { justify-content: space-between; width: 100%; }

  .checkout__bar { padding-inline: var(--gutter); }
  .checkout__body { padding-inline: var(--gutter); }

  /* Two numbered steps side by side, with the connector between them. */
  .steps { gap: var(--sp-3); }
  .steps__item { font-size: 10px; letter-spacing: 0.1em; }
  .steps__item:first-child::after { margin-left: var(--sp-2); }

  .checkout__actions { flex-direction: column-reverse; align-items: stretch; }
  .checkout__actions .btn { width: 100%; justify-content: space-between; }
  .checkout__actions .btn--primary { margin-right: 0; order: 0; }

  .summary-line { grid-template-columns: 30px minmax(0, 1fr) auto; }

  /* place-items: center leaves the panel content-sized, so `height: 100%`
     had nothing definite to resolve against and `max-height: none` removed
     the cap the scrolling depends on — the panel grew past the viewport and
     the fixed overlay clipped it, with no way to reach the bottom.
     Stretching the grid item and giving it a definite dvh height fixes it. */
  .detail { padding: 0; place-items: stretch; }

  .detail__panel {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    max-height: 100dvh;
    border: 0;
  }

  .detail__bar { padding-inline: var(--gutter); }
  .detail__info { padding: var(--sp-6) var(--gutter); }
  .detail__add { width: 100%; justify-content: space-between; }
  .recs { padding: var(--sp-6) var(--gutter); }

  .confirm__grid { gap: 0; }
}

/* --------------------------------------------------------------------------
   6. ACCOUNT
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .portal__body { padding-inline: var(--gutter); }

  .dash__head { flex-direction: column; align-items: stretch; gap: var(--sp-4); }
  .dash__head .btn { width: 100%; justify-content: center; }

  .dash__facts { grid-template-columns: minmax(0, 1fr); }

  .dash__fact {
    padding: var(--sp-4) 0;
    border-right: 0;
    border-bottom: var(--rule);
  }

  .dash__fact:last-child { border-bottom: 0; }

  .dash__claim { flex-direction: column; align-items: stretch; }
  .dash__claim .btn { width: 100%; justify-content: center; }

  .tabs__tab { flex: 1; text-align: center; justify-content: center; }
}

/* --------------------------------------------------------------------------
   7. ADMIN — the order table becomes a list of cards
   -------------------------------------------------------------------------- */
@media (max-width: 860px) {
  .admin__head { flex-direction: column; align-items: flex-start; }
  .admin__who { text-align: left; }

  .metrics { grid-template-columns: minmax(0, 1fr); }
  .metric { padding-right: 0; }

  .grid__scroll { overflow-x: visible; border-top: 0; }

  /* A six-column spreadsheet in a 330px window is unreadable however well it
     scrolls. Each order becomes a card, with the column headings carried down
     as labels on the cells that need them. */
  .grid,
  .grid tbody,
  .grid tr,
  .grid td {
    display: block;
    width: 100%;
  }

  .grid thead { display: none; }

  .grid tr {
    padding: var(--sp-5) 0;
    border-bottom: var(--rule);
  }

  .grid tr:hover td { background: transparent; }

  .grid td {
    padding: 0 0 var(--sp-3);
    border-bottom: 0;
  }

  .grid td:last-child { padding-bottom: 0; }

  /* The label comes from the data-label attribute admin.js writes. */
  .grid td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: var(--sp-2);
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: var(--tr-label);
    text-transform: uppercase;
    color: var(--text-faint);
  }

  .grid__id { font-size: var(--fs-small); }
  .grid__total { font-size: var(--fs-body); }
  .status-select { width: 100%; }

  .stock-row__fields { gap: var(--sp-3); }
  .stock-field { flex: 1 1 130px; }
  .stock-field__input { width: 100%; }
  .stock-row__reset { margin-left: 0; }

  /* Remove stops being pushed to the far right, where a thumb reaching for
     Edit lands on it instead. */
  .stock-row__actions { gap: var(--sp-3) var(--sp-5); }
  .row-link--danger { margin-left: 0; }

  .photo { flex-wrap: wrap; }
  .photo__actions { width: 100%; }

  .photos__add { flex-direction: column; align-items: stretch; }
  .photos__pick { width: 100%; justify-content: center; }
  .photos__url { flex: 1 1 auto; }
}

/* Full-width stacked buttons only where two of them genuinely will not fit
   side by side. Keyed on width AND height: a phone held sideways is 844px
   across but under 400px tall, and stacking there costs 100px of the little
   vertical room the dialog has — the body ends up shorter than its own
   footer. Cancel above Save so the primary action sits nearest the thumb. */
@media (max-width: 560px) and (min-height: 480px) {
  .editor__foot { flex-direction: column-reverse; }
  .editor__foot .btn { width: 100%; justify-content: center; }

  .ask__actions { flex-direction: column; }
  .ask__actions .btn { width: 100%; justify-content: center; }

  .promo-new__fields { flex-direction: column; align-items: stretch; }
  .promo-new__submit { width: 100%; justify-content: center; }

  .promo-row { flex-wrap: wrap; }
  .promo-row__used { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   8. TABLET — two columns where one would waste the width
   -------------------------------------------------------------------------- */
@media (min-width: 701px) and (max-width: 1024px) {
  .hero__body { grid-template-columns: minmax(0, 1fr); }
  .hero__actions { justify-content: flex-start; }
  .dash__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   9. LANDSCAPE PHONES — short screens should not be told to scroll a hero
   -------------------------------------------------------------------------- */
@media (max-height: 500px) and (orientation: landscape) {
  .hero__inner { min-height: auto; padding-block: var(--sp-7); }
  .nav__menu { padding-block: var(--sp-4); }
}

/* --------------------------------------------------------------------------
   10. LANDSCAPE PHONES — the detail view must still scroll
   -------------------------------------------------------------------------- */
@media (max-height: 560px) and (orientation: landscape) {
  .detail { padding: 0; }

  .detail__panel {
    width: 100%;
    height: 100%;
    max-height: 100dvh;
    border: 0;
  }

  /* Side by side rather than stacked: a 360px-tall window has no room for a
     full-width image above the copy. */
  .detail__grid { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr); }
  .detail__media { aspect-ratio: auto; border-bottom: 0; border-right: var(--rule); }
  .detail__info { padding: var(--sp-5); }
  .detail__title { font-size: var(--fs-h3); }
  .detail__description { margin-top: var(--sp-2); }

  .recs { padding: var(--sp-5); }
  [data-recs] { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Same trap as the detail view: these panels cap their height, so their
     scrolling child needs permission to shrink. */
  .checkout__body,
  .portal__body { min-height: 0; }

  /* THE BAG, SIDEWAYS.
     The drawer pins its head and its foot and scrolls only the middle. On a
     390px-tall screen that arrangement runs out of room: the head is 93px and
     the foot — promo field, four total lines, the checkout button and the
     fineprint — is 429px, which is 522px of fixed furniture in a 390px panel.
     The item list was handed what was left, namely zero, so the bag appeared
     empty; and the foot overflowed the panel, putting "Proceed to Checkout"
     at y=388 on a screen 390 tall. You could not see what you were buying and
     you could not reach the button to buy it.

     So on a short screen the whole panel scrolls as one column instead. Head,
     items and totals simply stack, and everything is reachable by scrolling —
     the behaviour a short window can actually honour. */
  .drawer__panel {
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  .drawer__body {
    flex: 0 0 auto;
    min-height: 0;
    overflow: visible;
  }

  .drawer__foot { flex: 0 0 auto; }

  /* The title and the close button stay put while the rest scrolls under
     them, so there is always a way out of the panel. */
  .drawer__head {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--bg);
  }
}

/* ==========================================================================
   POLISH — the final visual pass.

   Three rules, applied everywhere:

     1. Every text style states its line height. Nothing inherits a browser
        default, so nothing crowds at one size and gaps at another.
     2. Surfaces are one pitch black. Separation comes from the 1px rule and
        from type contrast, never from a lighter panel — the single exception
        being form fields, which have to read as somewhere you can type.
     3. Hover is short and consistent: 140ms on colour, border and background,
        and nothing moves the layout.
   ========================================================================== */

:root {
  /* One duration for every hover in the system. */
  --hover: 140ms var(--ease);
}

/* --------------------------------------------------------------------------
   Typography — explicit line heights
   -------------------------------------------------------------------------- */
.card__title,
.bag-item__title,
.stock-row__title,
.rec__title,
.summary-line__title,
.standards__title,
.panel__title,
.recs__title,
.drawer__title,
.dash__name,
.detail__title,
.checkout__step-title,
.catalog__title,
.admin__title,
.stub__title,
.modal__title { line-height: var(--lh-tight); }

.hero__headline { line-height: var(--lh-display); }

.card__description,
.rec__reason,
.standards__copy,
.summary-block__address,
.portal__notice,
.admin__warning,
.panel__empty,
.dash__empty,
.drawer__empty-copy,
.stub__copy,
.checkout__step-note,
.detail__description,
.payment__sim-copy { line-height: var(--lh-snug); }

.hero__lede,
.modal__copy { line-height: var(--lh-body); }

/* Mono is set at small sizes and wide tracking; it needs its own ratio or the
   labels sit too tight against what they label. */
.label,
.card__category,
.card__price,
.metric__label,
.metric__note,
.grid__email,
.orders__titles,
.promo__message,
.drawer__fineprint,
.confirm__fineprint,
.field__label,
.stock-field span,
.panel__note { line-height: var(--lh-mono); }

/* --------------------------------------------------------------------------
   Surfaces — pitch black everywhere, fields excepted
   -------------------------------------------------------------------------- */
.field__input,
.promo__input,
.stock-field__input,
.status-select {
  background-color: var(--bg-field);
}

/* A card no longer lightens on hover; the rule does the work instead. */
.card:hover,
.rec:hover { background: var(--bg); }

/* --------------------------------------------------------------------------
   Hover — one duration, no layout movement
   -------------------------------------------------------------------------- */
.card {
  transition: border-color var(--hover), background var(--hover);
}

.card:hover { border-color: var(--rule-color-strong); }

.rec {
  transition: border-color var(--hover), background var(--hover);
}

.rec:hover { border-color: var(--rule-color-strong); }

.btn,
.card__action,
.rec__add,
.pill,
.promo__apply,
.promo__remove,
.bag-item__remove,
.stepper__btn,
.nav__link,
.nav__cart,
.footer__link,
.tabs__tab,
.drawer__close,
.detail__close,
.summary-block__edit,
.stock-row__reset,
.promo-row__toggle,
.confirm__copy,
.status-select,
.field__input,
.promo__input,
.stock-field__input {
  transition: color var(--hover), background-color var(--hover),
              border-color var(--hover), opacity var(--hover);
}

/* The image is the one thing that moves, and only inside its own frame. */
.card__image { transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease); }

/* --------------------------------------------------------------------------
   Padding — symmetrical section rhythm at every width
   -------------------------------------------------------------------------- */
.catalog,
.standards,
.admin { padding-block: var(--section-y); }

.hero__inner { padding-block: var(--section-y); }

/* Sections that sit against the footer keep the same bottom as their top. */
.footer { padding-block: var(--section-y); }

/* ==========================================================================
   LOGO BAR — its own sticky strip, directly beneath the navigation.

   Two sticky elements stacked: the nav sticks to the top, this sticks to the
   nav's bottom edge (top: var(--nav-h)), so they travel down the page as one
   block. It sits a layer below the nav so the slide-out menu, which drops
   from the bar, passes over it.

   The <img> points at assets/img/logo.png. Until that file exists,
   assets/js/site.js swaps in the wordmark below, so the header is never a
   broken-image icon.
   ========================================================================== */
.logobar {
  position: sticky;
  /* Both sides of the shrink animate together, so the strip never looks like
     the padding and the artwork are moving at different speeds. */
  transition: padding var(--dur-base) var(--ease);
  top: var(--nav-h);
  z-index: calc(var(--z-nav) - 1);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(var(--sp-4), 2vw, var(--sp-5)) var(--gutter);
  background: var(--bg);
  border-bottom: var(--rule);
}

.logobar__link {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  /* The artwork is well over this, but the wordmark fallback that stands in
     when logo.png is missing is only ~40px tall — and it is a link home, so
     it still has to be reachable with a thumb. */
  min-height: 44px;
}

.logobar__img {
  display: block;
  width: auto;
  /* Full size at the top of the page. It shrinks once you scroll — see
     .logobar.is-compact below — so the header does not keep a third of the
     window for itself all the way down. */
  height: clamp(104px, 14vw, 168px);
  transition: height var(--dur-base) var(--ease);
  object-fit: contain;

  /* The artwork is black letterforms with white keylines, drawn for a white
     page. On a pitch-black strip the fills would vanish, so it is inverted:
     the fills come out porcelain and the surrounding white drops away. Works
     whether the file has a transparent or a white background.

     Supply a white/porcelain version one day and delete this single line. */
  filter: invert(1);
}

/* Shown only while assets/img/logo.png is missing. */
.logobar__fallback { display: none; }

.logobar__link[data-fallback] .logobar__img { display: none; }

.logobar__link[data-fallback] .logobar__fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-weight: var(--fw-black);
  font-size: clamp(1.125rem, 0.9rem + 1.1vw, 1.75rem);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-tight);
  text-transform: uppercase;
  color: var(--text);
  text-align: center;
}

.logobar__fallback em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tr-label);
  color: var(--text-faint);
}

/* The nav bar goes back to links left, cart right — the brand name is the
   strip below now, so the bar carries no wordmark of its own. */
.nav__brand {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.nav__inner { grid-template-columns: minmax(0, 1fr) auto; }
.nav__menu { grid-column: 1; grid-row: 1; justify-self: start; }
.nav__end  { grid-column: 2; grid-row: 1; justify-self: end; }

@media (max-width: 900px) {
  /* Same arrangement on a phone: the strip stays under the bar rather than
     collapsing into it. */
  .logobar { padding-block: var(--sp-4); }
  .logobar__img { height: clamp(88px, 22vw, 120px); }
  .logobar__link[data-fallback] .logobar__fallback { font-size: 1.0625rem; }
}

@media (max-height: 560px) and (orientation: landscape) {
  /* A short screen cannot spare 80px of logo above the fold. */
  .logobar { padding-block: var(--sp-3); }
  .logobar__img { height: 68px; }
}


/* --------------------------------------------------------------------------
   LOGO BAR — compact state, applied by assets/js/site.js past 48px of scroll
   -------------------------------------------------------------------------- */
.logobar.is-compact { padding-block: var(--sp-3); }

.logobar.is-compact .logobar__img { height: clamp(52px, 6vw, 72px); }

.logobar.is-compact .logobar__link[data-fallback] .logobar__fallback {
  font-size: clamp(0.875rem, 0.78rem + 0.5vw, 1.125rem);
  gap: 0;
}

/* 10px is the floor for mono labels everywhere; the compact wordmark is no
   exception, and "Roasting Co" was the one thing set below it. */
.logobar.is-compact .logobar__fallback em { font-size: 10px; }

@media (max-width: 900px) {
  .logobar.is-compact .logobar__img { height: clamp(40px, 9vw, 52px); }
  .logobar.is-compact .logobar__link[data-fallback] .logobar__fallback { font-size: 0.8125rem; }
}

@media (max-height: 560px) and (orientation: landscape) {
  /* Already small on a short screen; shrink it a little further and stop. */
  .logobar.is-compact .logobar__img { height: 40px; }
}

/* A size that jumps is fine; a size that jumps repeatedly is not. */
@media (prefers-reduced-motion: reduce) {
  .logobar,
  .logobar__img { transition: none; }
}
