/* Layout utilities the theme's Bootstrap build does not ship.
 *
 * Bootstrap 5.3 defines .overflow-x-auto, but the theme compiles its own
 * utilities map and leaves it out, so the class was a silent no-op wherever
 * a template used it. A row of buttons that cannot fit a phone has two
 * honest options - wrap, or scroll inside its own box - and this file
 * provides the second; the first is plain .flex-wrap.
 */
.overflow-x-auto { overflow-x: auto !important; }
.overflow-x-hidden { overflow-x: hidden !important; }

/* A one-line strip of controls that scrolls sideways when the viewport is
 * narrower than its contents. max-width is what keeps a flex child from
 * growing to its content and dragging its column past the page edge.
 *
 * overflow-y: hidden because overflow-x: auto makes the OTHER axis auto too,
 * and a strip of nav-tabs is 1px taller than its box (the theme's active-tab
 * indicator sits on the bottom border): the research page's tabs showed a
 * vertical scrollbar for that one pixel at every width. A one-line strip has
 * nothing to scroll vertically, and auto on x already clipped y. */
.scroll-strip {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.scroll-strip > * { flex-shrink: 0; white-space: nowrap; }

/* ---------- Icon wizards on a narrow screen -------------------------------
 *
 * The theme turns EVERY bs-stepper header into a vertical list below 992px
 * (vendor/libs/bs-stepper/bs-stepper.css: `.bs-stepper .bs-stepper-header
 * { flex-direction: column }`). At three short steps that is reasonable. The
 * two real wizards here have SIX - Story Developer (/app/scribe/develop) and
 * the publish wizard - so the header became a 297px stack on a 390px phone:
 * a third of the screen spent before any content, reading as a nav menu
 * rather than as progress, with no sense of position or distance left.
 *
 * Back to a rail, but a compact one: every step is its icon, and only the
 * step you are ON says its name. Six dots, one pill and five connectors
 * measure ~275px, so they fit a 390px phone with room; overflow-x is a
 * safety net for a longer wizard rather than the layout.
 *
 * Lives here rather than in a module sheet because both wizards ship the
 * same markup, and fit.css loads after the vendor block (master.html) so
 * source order already favours these rules. Scoped to `.wizard-icons` - the
 * variant that has icons to fall back on - so a numbered or vertical stepper
 * keeps the theme's behaviour.
 */
@media (max-width: 991.98px) {
  .bs-stepper.wizard-icons .bs-stepper-header {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-start;
    gap: 0.1rem;
    padding: 0.6rem 0.75rem;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .bs-stepper.wizard-icons .bs-stepper-header::-webkit-scrollbar {
    display: none;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .step {
    flex: 0 0 auto;
    min-width: 0;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .step .step-trigger {
    flex-direction: row;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
    padding: 0.3rem 0.35rem;
    border-radius: 2rem;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .step .step-trigger .bs-stepper-icon {
    margin: 0;
    line-height: 1;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .bs-stepper-icon i {
    font-size: 1.3rem;
  }

  /* Hidden to the EYE, not to the accessibility tree. The label is the
   * button's only accessible name, so display:none would leave five of the
   * six steps as unnamed buttons to a screen reader. */
  .bs-stepper.wizard-icons .bs-stepper-header .step .bs-stepper-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* The step you are on is the one that gets to speak. */
  .bs-stepper.wizard-icons .bs-stepper-header .step.active {
    flex: 0 1 auto;
    min-width: 0;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .step.active .step-trigger {
    background: rgba(var(--bs-primary-rgb), 0.12);
    padding-right: 0.7rem;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .step.active .bs-stepper-label {
    position: static;
    width: auto;
    height: auto;
    overflow: hidden;
    clip-path: none;
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    text-overflow: ellipsis;
  }

  /* Connectors: a rule between dots. The theme's chevron glyph is the right
   * idea at desktop width and noise at this size. */
  .bs-stepper.wizard-icons .bs-stepper-header .line {
    flex: 1 1 0.5rem;
    min-width: 0.3rem;
    max-width: 1.5rem;
    height: 2px;
    min-height: 0;
    margin: 0 0.1rem;
    padding: 0;
    align-self: center;
    background-color: var(--bs-border-color);
    border: 0;
  }

  .bs-stepper.wizard-icons .bs-stepper-header .line > i {
    display: none;
  }

  /* The run already behind you, filled in. `.crossed` is the library's own
   * marker; the :has() twin covers a step it has not marked (this wizard runs
   * linear:false, so you can arrive anywhere) and degrades to the plain
   * connector where :has() is unsupported. */
  .bs-stepper.wizard-icons .bs-stepper-header .step.crossed + .line,
  .bs-stepper.wizard-icons .bs-stepper-header .step:has(~ .step.active) + .line {
    background-color: rgba(var(--bs-primary-rgb), 0.5);
  }

  .bs-stepper.wizard-icons .bs-stepper-header .step:has(~ .step.active) .bs-stepper-icon i {
    color: rgba(var(--bs-primary-rgb), 0.75);
  }

  /* The stack left the content jammed against the header; the rail does not
   * need anything like that much air. */
  .bs-stepper.wizard-icons .bs-stepper-content {
    padding-top: 0.75rem;
  }
}

/* ---------- A notice must not be wider than the phone ----------------------
 *
 * A bullhorn banner carries whatever the thing that raised it was called, and
 * some of those names are one unbreakable word: a routine alert titled
 * "redfin__Climate_risks_flood_data_fire_data_heat_data_wind_data has never
 * worked" measured 475px of <strong> inside a 375px viewport, which pushed the
 * dismiss button off the right edge - so the notice could not be read OR
 * closed on a phone.
 *
 * Two rules, and BOTH are needed. A flex child defaults to min-width:auto,
 * which means it refuses to shrink below the intrinsic width of its longest
 * word, so the wrapping rule alone would never get a chance to apply; and
 * min-width:0 alone lets the box shrink while the word still juts out of it.
 *
 * `anywhere` rather than `break-word`: break-word will not break a word that
 * is alone on its line, which is exactly this case.
 */
.bullhorn-notice,
.bullhorn-notice > div,
.bullhorn-notice > div > div,
.bullhorn-notice .bullhorn-text,
.bullhorn-notice .bullhorn-body {
  min-width: 0;
}
.bullhorn-notice strong,
.bullhorn-notice span,
.bullhorn-notice a {
  overflow-wrap: anywhere;
  word-break: normal;
}
/* The close button keeps its size whatever the text does; it is the one part
   of a notice that must always be reachable. */
.bullhorn-notice .btn-close { flex: 0 0 auto; }

/* The sliding face has to be opaque in the NOTICE's colour, not the generic
   surface token core/css/swipe.css gives it: a notice paints its severity
   colour inline, so a paper-white face would slide a white slab across a red
   banner. `inherit` resolves to the parent's used background-color, which is
   that inline colour whatever the operator's palette makes it. */
.bullhorn-notice .swipe-face,
.bullhorn-toast .swipe-face {
  background-color: inherit;
}

/* ---------- Where a toast sits, and how much it covers --------------------
 *
 * A toast is position:fixed, so it does not push the page down - it lies on
 * top of it, and whatever is underneath cannot be touched at all. On a desktop
 * it tucks into the top-right corner and overlaps nothing that matters. On a
 * 390px phone it is nearly the full width, it was measured at 295px tall, and
 * the top corner is exactly where the bullhorn BANNER is: the toast covered it
 * completely, so every touch aimed at the banner hit the toast instead. The
 * banner could not be swiped, tapped, or closed while a toast was up, and a
 * vertical drag scrolled the page because the toast does not scroll.
 *
 * Two changes, and both are needed. Bottom on a phone, so a toast and the
 * page's own header are never fighting for the same pixels. And a clamped
 * body, because the toast being a THIRD OF THE SCREEN TALL is its own problem
 * - a transient popup that size is a page takeover.
 */
.bullhorn-toast-container {
  top: 0;
  right: 0;
}

@media (max-width: 767.98px) {
  .bullhorn-toast-container {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    /* column-reverse puts the newest toast nearest the thumb. Without it the
       newest appears furthest away and the stack grows upwards, back into the
       content this move was made to stop covering. */
    display: flex;
    flex-direction: column-reverse;
    gap: .5rem;
  }
  .bullhorn-toast .bullhorn-body {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* On a phone the title, the body and the action stack rather than fighting
   for one line beside the button. */
@media (max-width: 575.98px) {
  .bullhorn-notice > div {
    align-items: flex-start !important;
    gap: .5rem;
  }
}

/* ---------- How much of a phone a notice may take -------------------------
 *
 * A notice carries a title, a body of whatever length the thing that raised it
 * wrote, and an action link. On a 390x844 phone one of them measured 157px -
 * nineteen per cent of the screen - above the page the reader actually came
 * for. It is the same notice on a desktop and costs nothing there.
 *
 * Clamped to three lines, which is enough to know what it is about and whether
 * it is for you. Tapping opens it, because a notice nobody can finish reading
 * is worse than one that takes the room. The cue and the tap are added by
 * bullhorn.js and ONLY when the text is actually cut off - a two-line notice
 * that fits must not offer to expand and then do nothing.
 */
@media (max-width: 767.98px) {
  .bullhorn-notice .bullhorn-body {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  /* Two lines on the smallest screens. Three lines cost 114px of a 508px
     phone, and Read more is right there. */
  @media (max-height: 560px), (max-width: 380px) {
    .bullhorn-notice .bullhorn-body { -webkit-line-clamp: 2; }
  }
  .bullhorn-notice.bullhorn-open .bullhorn-body {
    display: block;
    -webkit-line-clamp: none;
    overflow: visible;
  }
  /* The cue is a real control and a SIBLING of the clamped block, not a
     pseudo-element inside it: anything inside is on the fourth line and gets
     clipped away with the rest, so it would appear only once the notice was
     already open, which is the one moment it is not needed. */
  .bullhorn-notice .bullhorn-more {
    display: inline-block;
    background: none;
    border: 0;
    padding: .15rem 0 0;
    font-size: .8125rem;
    text-decoration: underline;
    color: inherit;
    opacity: .85;
  }
  /* The clipped text is a target too, so a thumb does not have to find a
     one-line link. */
  .bullhorn-notice.bullhorn-clipped .bullhorn-body { cursor: pointer; }
}

/* Above the clamp there is nothing to expand, so the control does not exist -
   rather than being hidden and still read out by a screen reader. */
@media (min-width: 768px) {
  .bullhorn-notice .bullhorn-more { display: none; }
}

/* ---------- Which column of a data table gets the room --------------------
 *
 * A table in .table-responsive already scrolls rather than overflowing the
 * page, so nothing in one is unreachable - but scrolling does not decide WHICH
 * column gets the space, and the browser hands it out by content, not by
 * importance. On the storefront products list at 375px the name had 110px for
 * "AFEW Cap / afew-cap / 1 variant(s)" while the price had 103px for "24.00"
 * and the state 127px for a single badge.
 *
 * These live HERE, not in a module stylesheet, because the first attempt put
 * them in commerce/shop.css - which the products list loads and the category,
 * collection, product-type, attribute and warehouse lists do not. The rules
 * worked on exactly one of the pages they were written for. master.html loads
 * fit.css on every page.
 *
 *   .tcol-tight  a column whose content has a natural width: a number, a
 *                badge, a date, a row of buttons. `width: 1%` is the old
 *                table trick for "take only what you need" - a percentage
 *                that small cannot be honoured, so the browser falls back to
 *                the content width and the leftover goes to the columns
 *                without it. NEVER on a column of prose: it carries nowrap.
 *
 *   .tcol-main   the column the row is ABOUT. It gets the slack and a floor,
 *                so on a narrow screen it stops shrinking and the table
 *                scrolls instead. A name you can read after a swipe beats one
 *                you can never read at all.
 *
 * Put the class on the th AND the td, or the column disagrees with itself.
 */
.tcol-tight { width: 1%; white-space: nowrap; }
.tcol-main { min-width: 11rem; }

/* A whole table in one class, for the shape that keeps recurring: a name and
 * then nothing but numbers - usage by model, tokens by harness, spend by key.
 * Every column after the first is a figure with a natural width, so naming
 * them one by one is six copies of the same decision, and half of these
 * tables build their rows in JavaScript where the th classes never reach the
 * cells. `.tcol-metrics` on the <table> says it once for the whole grid.
 *
 * Only for a table whose every non-first column is a number or a badge. A
 * column of prose in here would be given nowrap and run off the edge.
 */
.tcol-metrics > :is(thead, tbody) > tr > :is(th, td):not(:first-child) {
  width: 1%;
  white-space: nowrap;
}
.tcol-metrics > :is(thead, tbody) > tr > :is(th, td):first-child { min-width: 11rem; }
@media (min-width: 992px) {
  .tcol-metrics > :is(thead, tbody) > tr > :is(th, td):first-child { min-width: 0; }
}

/* A name cell usually carries a second line - a slug, an SKU, an email - and
   those are often one unbreakable token. It wraps rather than forcing the
   column past its floor. */
.tcol-main .small,
.tcol-main .text-muted { overflow-wrap: anywhere; }

@media (min-width: 992px) {
  /* With room to spare the floor stops mattering and a table lays out as it
     always did. */
  .tcol-main { min-width: 0; }
}

/* ---------- A button is as wide as its label ------------------------------
 *
 * A card header that lines up a title, a filter and an action button is a
 * flex row, and Bootstrap's flex rows do not wrap. On a phone there is not
 * room for all three, so the row does the only other thing it can: it squeezes
 * the children. The button is the one that loses, because a title can
 * truncate and a button cannot - "New warehouse" got 75px for a label needing
 * 107, and the text spilled out of its own box.
 *
 * Two rules. The header may break onto a second line, which only happens when
 * the contents would not have fitted anyway; and the button stops shrinking,
 * so it is never narrower than the words on it.
 *
 * Deliberately not `.btn { flex-shrink: 0 }` everywhere: a button inside a
 * flex row that MUST fit one line (a toolbar, an input group) is entitled to
 * shrink, and taking that away trades a clipped label for a page that
 * overflows sideways.
 */
.card-header.d-flex { flex-wrap: wrap; }
.card-header .btn,
.card-header .btn-group { flex-shrink: 0; }

/* `hidden` hides a button. The theme gives .btn `display: inline-flex
 * !important`, which outranks the user agent's [hidden] rule, so a button a
 * script hid stayed on screen: the mission page showed Pause, Resume and Stop
 * together whatever the mission was doing. */
.btn[hidden], .badge[hidden] { display: none !important; }
/* ...and the same for Bootstrap's display utilities, which are !important by
 * design: a `d-flex` form a script hid stayed on screen (the mission page's
 * "Add and resume" showed on a finished mission). */
[hidden]:is(.d-flex, .d-inline-flex, .d-block, .d-inline-block, .d-inline, .d-grid, .d-table) { display: none !important; }
