/* Design tokens the shared convention sheet (bma_ui.css) reads. Brand and accent per
   BMA_UX_CONVENTIONS III: one accent carries attention, "needs input" and error. */
:root {
  --brand: #306CC0;
  --accent: #D8306C;
}

/* BuildMyApp custom styles */
body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

main {
    flex: 1;
}

/* ── Mobile navbar: a slide-out panel ──
   Below lg the menu is a panel that slides in from the right under the navbar,
   sized to its content rather than the screen. The navbar stays visible, so the
   hamburger remains the way to close it and no second close control is needed.

   --bma-navbar-h is measured and set by mobile-nav.js. The fallback covers the
   frame before that runs. */
@media (max-width: 991.98px) {
    /* Rendered at all times and moved with a transform, rather than Bootstrap's
       display toggle: an element that is display:none cannot animate in, and
       the height animation belongs to a vertical accordion, not a slide. */
    #navbarNav.navbar-collapse,
    #navbarNav.navbar-collapse.collapsing,
    #navbarNav.navbar-collapse.show {
        display: flex !important;
        flex-direction: column !important;
        align-items: stretch;
        height: auto !important;
        transition: none;

        position: fixed;
        top: var(--bma-navbar-h, 64px);
        right: 0;
        width: 67%;
        max-width: 340px;
        max-height: calc(100vh - var(--bma-navbar-h, 64px));
        max-height: calc(100dvh - var(--bma-navbar-h, 64px));
        overflow-y: auto;
        z-index: 1035;

        background: #1B2027;
        border-bottom: 3px solid #306CC0;
        border-bottom-left-radius: 0.625rem;
        box-shadow: -8px 8px 26px rgba(0, 0, 0, 0.34);

        transform: translateX(100%);
        visibility: hidden;
        transition: transform 240ms cubic-bezier(0.32, 0.72, 0, 1),
                    visibility 0s linear 240ms;
    }

    #navbarNav.navbar-collapse.show {
        transform: translateX(0);
        visibility: visible;
        transition: transform 240ms cubic-bezier(0.32, 0.72, 0, 1),
                    visibility 0s;
    }

    #navbarNav .navbar-nav {
        /* !important, or the utility class on the <ul> wins and the row comes
           back. The utilities are lg-prefixed now, so this is belt and braces. */
        flex-direction: column !important;
        flex-wrap: nowrap !important;
        align-items: stretch;
        gap: 0;
        width: 100%;
    }

    #navbarNav .navbar-nav .nav-link {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        min-height: 52px;
        padding: 0 1.125rem;
        color: #fff;
        white-space: nowrap;
        border-top: 1px solid rgba(255, 255, 255, 0.08);
    }

    /* No rule above the first row: the panel edge already is one. */
    #navbarNav .navbar-nav:first-of-type .nav-item:first-child .nav-link {
        border-top: 0;
    }

    #navbarNav .nav-ic {
        width: 22px;
        flex: 0 0 22px;
        text-align: center;
        opacity: 0.75;
        font-size: 0.95rem;
    }

    /* A full-width rule between the site links and the account menu. It was a
       1px vertical bar, which only read as a separator in a horizontal row. */
    .nav-divider {
        width: 100%;
        height: 1px;
        background-color: rgba(255, 255, 255, 0.25);
        margin: 0.5rem 0;
    }

    /* The account list expands in place. It used to break out as a white card,
       right-aligned and floating over the page behind the menu.

       That was not Popper: Bootstrap skips Popper for dropdowns inside a navbar
       and already renders them statically while the navbar is collapsed. The
       card came from this stylesheet overriding that with
       `position: absolute !important; right: 0; top: 100%`. Restating static
       here is the direct antidote, and mutating it back reproduces the bug. */
    #navbarNav .dropdown-menu {
        position: static !important;
        display: none;
        float: none;
        width: 100%;
        margin: 0;
        padding: 0;
        background: rgba(0, 0, 0, 0.22);
        border: 0;
        border-radius: 0;
    }

    #navbarNav .dropdown-menu.show {
        display: block;
    }

    #navbarNav .dropdown-item {
        display: flex;
        align-items: center;
        min-height: 46px;
        padding: 0 1.125rem 0 3.25rem;
        color: rgba(255, 255, 255, 0.82);
        border-top: 1px solid rgba(255, 255, 255, 0.06);
        white-space: nowrap;
    }

    #navbarNav .dropdown-item:hover,
    #navbarNav .dropdown-item:focus {
        background: rgba(255, 255, 255, 0.06);
        color: #fff;
    }

    #navbarNav .dropdown-divider {
        margin: 0;
        border-top-color: rgba(255, 255, 255, 0.12);
    }

    /* While the menu is open the navbar outranks everything, because the panel
       lives inside it. A z-index on a child cannot escape its parent's stacking
       context, so the panel's 1035 counts only against its siblings inside the
       navbar; against the page it is the navbar's own z-index that decides.
       Without this the scrim paints over the panel and swallows every tap.

       !important because /requests/new also sets a z-index on the navbar, with
       a more specific selector, to sit above its pinned chat pane. */
    body.nav-open > .navbar {
        position: relative;
        z-index: 1036 !important;
    }

    /* Dims the page and gives somewhere to tap to close. Starts below the
       navbar so the hamburger stays available. */
    #nav-scrim {
        pointer-events: none;
        position: fixed;
        top: var(--bma-navbar-h, 64px);
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1034;
        background: rgba(8, 12, 18, 0.5);
        opacity: 0;
        visibility: hidden;
        transition: opacity 200ms ease, visibility 0s linear 200ms;
    }

    body.nav-open #nav-scrim {
        pointer-events: auto;
        opacity: 1;
        visibility: visible;
        transition: opacity 200ms ease, visibility 0s;
    }
}

/* The icons are a mobile affordance. Desktop keeps the text-only navbar. */
@media (min-width: 992px) {
    .nav-ic { display: none; }
    #nav-scrim { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    #navbarNav.navbar-collapse,
    #navbarNav.navbar-collapse.show,
    #nav-scrim {
        transition: none;
    }
}

/* ── Global: enforce minimum touch targets ── */
.btn-sm {
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.nav-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
}

/* The one control on a phone that every page depends on, and it was 40px. */
.navbar-toggler {
    min-height: 44px;
    min-width: 44px;
}

.list-group-item-action {
    min-height: 44px;
}

.form-check-input {
    min-width: 20px;
    min-height: 20px;
}

/* ── Global: prevent long URLs/text from overflowing ── */
.card-body a[href*="github"],
.card-body a[target="_blank"] {
    word-break: break-all;
}

/* ── Responsive table wrapper ── */
.table-responsive-auto {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* ── Mobile styles (phones, < 576px) ── */
@media (max-width: 575.98px) {
    /* Minimum readable font sizes */
    body {
        font-size: 1rem; /* 16px */
    }

    .small, small {
        font-size: 0.875rem; /* 14px floor */
    }

    /* Landing: wrap hero CTA buttons */
    .hero-cta {
        flex-wrap: wrap;
    }

    /* Browse: stack request card price to below title */
    .request-card-layout {
        flex-direction: column;
    }

    .request-card-price {
        min-width: unset !important;
        text-align: left !important;
        margin-left: 0 !important;
        margin-top: 0.75rem;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.5rem;
    }

    .request-card-price .d-flex {
        justify-content: flex-start !important;
    }

    /* Browse: filter form — full-width columns on mobile */
    .browse-filters .col-md-3,
    .browse-filters .col-md-2,
    .browse-filters .col-md-1 {
        flex: 0 0 50%;
        max-width: 50%;
    }

    .browse-filters .col-md-1 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* Dashboard: truncate long tab labels */
    #dashboardTabs .nav-link {
        font-size: 0.875rem;
        padding: 0.5rem 0.75rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 50vw;
    }

    /* Proposal card: stack layout on mobile */
    .proposal-card-layout {
        flex-direction: column;
    }

    /* Commit history: stack layout on mobile */
    .commit-check-layout {
        flex-direction: column;
        gap: 0.5rem;
    }

    /* Request detail: wrap title + badge row */
    .request-title-row {
        flex-direction: column;
        align-items: flex-start !important;
        gap: 0.5rem;
    }

    /* Modal: ensure modals don't overflow */
    .modal-dialog {
        margin: 0.5rem;
    }

    /* Tables: make them scrollable */
    .table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* Ensure adequate spacing between tappable elements */
    .d-flex.gap-2 {
        gap: 0.75rem !important;
    }

    .badge {
        padding: 0.35em 0.65em;
        font-size: 0.8rem;
    }
}

/* ── Tablet styles (576px - 767px) ── */
@media (min-width: 576px) and (max-width: 767.98px) {
    /* Browse filters: better column distribution */
    .browse-filters .col-md-1 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    .request-card-price {
        min-width: 100px !important;
    }
}

/* Settings progress card: brief row-pulse when a button-only row is jumped
   to via the progress card. Used by static/js/app.js (functional #13). */
@keyframes bma-pulse-fade {
  0%   { background-color: var(--bs-warning-bg-subtle, #fff3cd); }
  100% { background-color: transparent; }
}
.bma-pulse {
  animation: bma-pulse-fade 1.4s ease-out 1;
}

/* Rendered markdown for proposal messages (services/markdown_rendering.py
   + safe_markdown Jinja filter). Tight spacing so the proposal reads as
   one block, not a sea of margins. */
.proposal-message-rendered > :first-child { margin-top: 0; }
.proposal-message-rendered > :last-child  { margin-bottom: 0; }
.proposal-message-rendered p { margin-bottom: 0.65rem; }
.proposal-message-rendered h1,
.proposal-message-rendered h2,
.proposal-message-rendered h3,
.proposal-message-rendered h4 {
  margin-top: 1rem;
  margin-bottom: 0.5rem;
  font-weight: 600;
}
.proposal-message-rendered h1 { font-size: 1.4rem; }
.proposal-message-rendered h2 { font-size: 1.25rem; }
.proposal-message-rendered h3 { font-size: 1.1rem; }
.proposal-message-rendered h4 { font-size: 1rem; }
.proposal-message-rendered ul,
.proposal-message-rendered ol { margin-bottom: 0.65rem; padding-left: 1.5rem; }
.proposal-message-rendered li { margin-bottom: 0.15rem; }
.proposal-message-rendered blockquote {
  border-left: 3px solid #dee2e6;
  padding: 0.25rem 0.75rem;
  color: #495057;
  margin: 0.5rem 0;
}
.proposal-message-rendered code {
  background-color: #f1f3f5;
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
  font-size: 0.9em;
}
.proposal-message-rendered pre {
  background-color: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 4px;
  padding: 0.65rem 0.75rem;
  overflow-x: auto;
}
.proposal-message-rendered pre code {
  background: transparent;
  padding: 0;
}
.proposal-message-rendered hr {
  margin: 1rem 0;
  border-top: 1px solid #dee2e6;
}
.proposal-message-rendered a { color: #306CC0; }
.proposal-message-rendered a:hover { color: #1f4e8a; }
.proposal-message-rendered table {
  width: 100%;
  margin: 0.75rem 0;
  border-collapse: collapse;
  font-size: 0.95em;
  display: block;
  overflow-x: auto;
}
.proposal-message-rendered th,
.proposal-message-rendered td {
  border: 1px solid #dee2e6;
  padding: 0.4rem 0.6rem;
  vertical-align: top;
}
.proposal-message-rendered thead th {
  background-color: #f8f9fa;
  font-weight: 600;
}
@media (min-width: 576px) {
  .proposal-message-rendered table { display: table; }
}

/* Terms re-agreement diff: insertions and strikethrough deletions in BMA accent color. */
.terms-diff ins {
  color: #d8306c;
  text-decoration: none;
  background: transparent;
}
.terms-diff del {
  color: #d8306c;
  text-decoration: line-through;
  background: transparent;
}

/* Reputation badge tier colors (sub-ticket #7).
   Scoped under .rep-badge to avoid collision with Bootstrap utilities. */
.rep-badge {
    font-weight: 600;
}
.rep-badge[role="button"] {
    cursor: pointer;
}
.rep-badge.tier-excellent {
    background-color: #198754;
    color: #ffffff;
}
.rep-badge.tier-good {
    background-color: #0d6efd;
    color: #ffffff;
}
.rep-badge.tier-fair {
    background-color: #ffc107;
    color: #000000;
}
.rep-badge.tier-poor {
    background-color: #dc3545;
    color: #ffffff;
}
.rep-badge.tier-pending {
    background-color: #6c757d;
    color: #ffffff;
}

/* ── Required-field affordance (BMA_UX_CONVENTIONS) ──
   A required, empty field signals that input is needed in the accent color:
   a tinted control plus a small "Required" tag. Accent is #D8306C. */
.bg-accent-subtle { background-color: rgba(216, 48, 108, 0.12); }
.text-accent { color: #D8306C; }
.border-accent { border-color: #D8306C; }

/* ── Open-question banner (outstanding questions, 2026-08-16) ──
   Pinned above the collaboration message list, never inside it. Accent
   (#D8306C) because BMA_UX_CONVENTIONS III spends the accent on "input is
   needed"; the resolved variant is green, which is semantic state rather than
   attention, since by then no input is needed. */
.oq {
    border: 1px solid rgba(216, 48, 108, 0.34);
    border-left: 4px solid #D8306C;
    background: rgba(216, 48, 108, 0.055);
    border-radius: 6px;
    padding: 12px 14px;
    margin-bottom: 0.75rem;
}
.oq:last-child { margin-bottom: 0; }
.oq-top {
    display: flex;
    align-items: center;
    gap: 9px;
    flex-wrap: wrap;
}
.oq-icon { color: #D8306C; flex: none; }
.oq-title { font-weight: 700; color: #A31F50; }
.oq-age {
    margin-left: auto;
    font-size: 0.75rem;
    font-weight: 600;
    color: #A31F50;
    background: rgba(216, 48, 108, 0.13);
    padding: 3px 8px;
    border-radius: 20px;
    white-space: nowrap;
}
.oq-item {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 9px 0 0 27px;
}
.oq-item .q { flex: 1 1 auto; }
.oq-foot {
    padding: 10px 0 0 27px;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.oq--resolved {
    border-color: rgba(25, 135, 84, 0.32);
    border-left-color: #198754;
    background: rgba(25, 135, 84, 0.05);
}
.oq--resolved .oq-icon { color: #198754; }
.oq--resolved .oq-title { color: #146c43; }

.btn-outline-accent {
    color: #D8306C;
    border-color: #D8306C;
    background-color: #FFFFFF;
    font-weight: 600;
}
.btn-outline-accent:hover,
.btn-outline-accent:focus {
    color: #FFFFFF;
    background-color: #D8306C;
    border-color: #D8306C;
}

/* The in-thread marker: scrolling past an open question has to read as open
   rather than as ordinary history. */
.collab-msg--awaiting .card { 
    background: rgba(216, 48, 108, 0.055) !important;
    border: 1px solid rgba(216, 48, 108, 0.28) !important;
    border-left: 3px solid #D8306C !important;
}
.msg-flag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #A31F50;
    background: rgba(216, 48, 108, 0.12);
    padding: 3px 8px;
    border-radius: 4px;
    margin-left: 8px;
}
.msg-flag--done {
    color: #146c43;
    background: rgba(25, 135, 84, 0.13);
}

@media (max-width: 575.98px) {
    .oq-item, .oq-foot { padding-left: 0; }
    .oq-age { margin-left: 0; }
}

/* ---------------------------------------------------------------------------
   The assistant conversation attached to a posted request or listing, read
   back by its author on the request/listing page. Author-only; see
   templates/_composer_conversation.html.
   --------------------------------------------------------------------------- */

.composer-conversation [aria-expanded="false"] .collapse-label-hide,
.composer-conversation [aria-expanded="true"] .collapse-label-show {
    display: none;
}

.composer-conversation-log {
    max-height: 26rem;
    overflow-y: auto;
}

.composer-turn { margin-bottom: 0.9rem; }
.composer-turn:last-child { margin-bottom: 0; }

.composer-turn-who {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #6c757d;
    margin-bottom: 0.2rem;
}

.composer-turn-text {
    border-left: 3px solid #dee2e6;
    padding: 0.15rem 0 0.15rem 0.75rem;
    white-space: pre-wrap;   /* the buyer typed paragraphs; keep them */
    overflow-wrap: anywhere; /* a pasted URL must not widen the card */
}

.composer-turn-assistant .composer-turn-text { border-left-color: #306CC0; }
.composer-turn-user .composer-turn-text { border-left-color: #adb5bd; }

/* ---------------------------------------------------------------------------
   Restored-draft note in the collaboration composer. Shown only when a draft
   came back without the attachments that were pending when it was saved, so it
   is always actionable: the reader has to re-add a file before sending.
   Accent-coloured for that reason, per the attention convention.
   --------------------------------------------------------------------------- */

.collab-draft-note {
    color: #D8306C;
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
}

.collab-draft-note::before {
    content: "!";
    flex: 0 0 auto;
    width: 1rem;
    height: 1rem;
    line-height: 1rem;
    text-align: center;
    font-weight: 700;
    font-size: 0.7rem;
    border-radius: 50%;
    border: 1px solid currentColor;
}

.collab-draft-note[hidden] { display: none; }
