/* Convene custom styles — supplements Pico CSS */

/* Badge base definition is in shared narratory-spa.css (see
 * Narratory/design_standards.md §11). This block maps Convene's
 * domain-specific data-status values to the five shared semantic
 * tokens so existing templates (which use data-status="scheduled" etc.)
 * don't need to change. New Convene code should prefer
 * <span class="badge" data-variant="success">Confirmed</span>
 * directly when the template-side status is flexible.
 */

/* success */
.badge[data-status="confirmed"],
.badge[data-status="active"],
.badge[data-status="approved"],
.badge[data-status="completed"]           { background: var(--status-success); }

/* info */
.badge[data-status="scheduled"],
.badge[data-status="public"],
.badge[data-status="recap_distributed"],
.badge[data-status="processing"]          { background: var(--status-info); }

/* warning */
.badge[data-status="pending_review"],
.badge[data-status="invited"],
.badge[data-status="pending"]             { background: var(--status-warning); }

/* danger */
.badge[data-status="cancelled"],
.badge[data-status="rejected"]            { background: var(--status-danger); }

/* neutral */
.badge[data-status="archived"],
.badge[data-status="private"],
.badge[data-status="withdrawn"]           { background: var(--status-neutral); }

/* Convene-specific statuses that don't fit the five semantic buckets —
 * kept as local overrides. If another product needs an "accent" color
 * for a similar "in-flight" state, promote to the shared tokens. */
.badge[data-status="soliciting"]          { background: #7c3aed; }
.badge[data-status="recap_draft"]       { background: #8b5cf6; }

/* Derived occurrence "tone" — the admin UI renders the human-meaning badge
 * (state.tone) instead of the raw machine status. Mapped to the same five
 * shared semantic tokens as data-status above. Defined locally (rather than
 * relying on the shared data-variant attribute) so rendering is self-contained
 * regardless of the CDN bundle version. See services/occurrence_state.py. */
.badge[data-tone="success"] { background: var(--status-success); }
.badge[data-tone="info"]    { background: var(--status-info); }
.badge[data-tone="warning"] { background: var(--status-warning); }
.badge[data-tone="danger"]  { background: var(--status-danger); }
.badge[data-tone="neutral"] { background: var(--status-neutral); }

/* Agenda "what to do" banner under the status bar. Warning = it's the admin's
 * turn (finalize / review); info = informational ("community is voting"). */
.agenda-action-banner {
    margin-top: 0.5rem;
    padding: 0.4rem 0.6rem;
    border-radius: 0.25rem;
    font-size: 0.85rem;
    line-height: 1.35;
}
.agenda-action-banner[data-tone="warning"] {
    background: color-mix(in srgb, var(--status-warning) 15%, transparent);
    border-left: 3px solid var(--status-warning);
}
.agenda-action-banner[data-tone="info"] {
    background: color-mix(in srgb, var(--status-info) 12%, transparent);
    border-left: 3px solid var(--status-info);
}

/* Connect: Convene→Cohost sourcing-readiness checklist, shown under the
 * source_a_to_b capability on a connection card. Surfaces the
 * recap_publicly_viewable gate so an admin can see why meetings aren't
 * producing episodes. Tones mirror .agenda-action-banner. */
.source-readiness {
    margin-top: 0.5rem;
    padding: 0.5rem 0.6rem;
    border-radius: 0.25rem;
    font-size: 0.85rem;
    line-height: 1.35;
    background: color-mix(in srgb, var(--status-info) 10%, transparent);
    border-left: 3px solid var(--status-info);
}
.source-readiness[data-ready="true"] {
    background: color-mix(in srgb, var(--status-success) 10%, transparent);
    border-left-color: var(--status-success);
}
.source-readiness .sr-head { font-weight: 600; margin: 0 0 0.35rem; }
.source-readiness ul { list-style: none; margin: 0; padding: 0; }
.source-readiness li { margin: 0.15rem 0; }
.source-readiness .sr-mark { margin-right: 0.35rem; font-weight: 700; }
.source-readiness li[data-ok="true"]  .sr-mark { color: var(--status-success); }
.source-readiness li[data-ok="false"] .sr-mark { color: var(--status-danger); }
.source-readiness .sr-hint { display: block; margin-left: 1.2rem; color: var(--pico-muted-color); }
.source-readiness .sr-foot { margin: 0.4rem 0 0; color: var(--pico-muted-color); }

/* Presenter avatar on the public occurrence lineup. Always rendered: a member
   with no headshot falls back to /static/img/avatar-placeholder.svg rather
   than dropping the element, so a lineup mixing people with and without a
   photo keeps one left edge instead of ragging in and out. Fixed square +
   object-fit means an off-square upload can't change a row's height either. */
.speaker-avatar {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--pico-muted-border-color);
}

/* Contribution type color dot */
.type-dot {
    display: inline-block;
    width: 0.75em;
    height: 0.75em;
    border-radius: 50%;
    margin-right: 0.25em;
    vertical-align: middle;
}

/* Shared Narratory SPA chrome (.nav-user, .product-switcher, .admin-layout,
 * .admin-sidebar, .admin-panel, .landing-card, responsive breakpoints, alert base)
 * lives in https://narratory.com/static/narratory-spa.css. */

/* Sub-nav and sub-panel CSS now lives in narratory-spa.css (see
 * SPA_dashboard_standards.md §20) — this product no longer overrides it. */

/* .sort-card shell (handle + body + actions) moved to shared
 * narratory-spa.css — see design_standards.md §13.
 *
 * .agenda-divider is a Convene-specific dashed separator between
 * approved and carry-forward submissions in the agenda list — kept
 * as a local class.
 */
.agenda-divider {
    border: 1px dashed var(--pico-del-color);
    text-align: center;
    padding: 0.25rem;
    font-size: 0.75rem;
    color: var(--pico-del-color);
    margin: 0.5rem 0;
}

/* Moderation queue — held submissions awaiting admit/decline. Framed as a
 * distinct amber callout (mirroring .agenda-action-banner[warning]) so it
 * reads as a separate inbox, not part of the agenda running order below. */
.moderation-queue {
    background: color-mix(in srgb, var(--status-warning) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--status-warning) 40%, transparent);
    border-left: 4px solid var(--status-warning);
    border-radius: 0.4rem;
    padding: 0.75rem 0.85rem;
    margin-bottom: 1.25rem;
}
.moderation-queue .mq-head {
    font-weight: 700;
    font-size: 0.95rem;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.25rem;
}
.moderation-queue .mq-help {
    font-size: 0.8rem;
    color: var(--pico-muted-color);
    margin-bottom: 0.6rem;
    line-height: 1.4;
}
/* The agenda (running order) section heading + its action helper text — same
 * muted format as .mq-help, so the two sections read as siblings. */
.agenda-section-head {
    font-weight: 700;
    font-size: 0.95rem;
    margin-bottom: 0.15rem;
}
.agenda-help {
    font-size: 0.8rem;
    color: var(--pico-muted-color);
    margin: 0 0 0.6rem;
    line-height: 1.4;
}

/* .sortable-ghost moved to shared narratory-spa.css — see design_standards.md §7. */

/* Mobile sub-nav grid override — also moved to narratory-spa.css §20.
 * Keeping this block empty as a placeholder for future product-specific
 * mobile tweaks. */

/* Table cell spacing + dialog max-width moved to shared narratory-spa.css.
 * See design_standards.md §5 and §6. */

/* Inline input+button rows: kill Pico's default bottom margin so items align */
[style*="display:flex"][style*="align-items:center"] > input,
[style*="display:flex"][style*="align-items:center"] > select,
[style*="display:flex"][style*="align-items:center"] > button,
[style*="display:flex"][style*="align-items:center"] > label,
[style*="display:flex"][style*="align-items:center"] > [role="button"],
[style*="display: flex"][style*="align-items: center"] > input,
[style*="display: flex"][style*="align-items: center"] > select,
[style*="display: flex"][style*="align-items: center"] > button,
[style*="display: flex"][style*="align-items: center"] > label,
[style*="display: flex"][style*="align-items: center"] > [role="button"],
[style*="display:flex"][style*="align-items:flex-end"] > input,
[style*="display:flex"][style*="align-items:flex-end"] > select,
[style*="display:flex"][style*="align-items:flex-end"] > button,
[style*="display:flex"][style*="align-items:flex-end"] > label,
[style*="display:flex"][style*="align-items:flex-end"] > [role="button"],
[style*="display: flex"][style*="align-items: flex-end"] > input,
[style*="display: flex"][style*="align-items: flex-end"] > select,
[style*="display: flex"][style*="align-items: flex-end"] > button,
[style*="display: flex"][style*="align-items: flex-end"] > label,
[style*="display: flex"][style*="align-items: flex-end"] > [role="button"],
[style*="display:flex"][style*="align-items:stretch"] > input,
[style*="display:flex"][style*="align-items:stretch"] > select,
[style*="display:flex"][style*="align-items:stretch"] > button,
[style*="display:flex"][style*="align-items:stretch"] > label,
[style*="display:flex"][style*="align-items:stretch"] > [role="button"],
[style*="display: flex"][style*="align-items: stretch"] > input,
[style*="display: flex"][style*="align-items: stretch"] > select,
[style*="display: flex"][style*="align-items: stretch"] > button,
[style*="display: flex"][style*="align-items: stretch"] > label,
[style*="display: flex"][style*="align-items: stretch"] > [role="button"] {
    margin-bottom: 0;
}

/* Breadcrumb nav (Pico doesn't have one by default) */
nav[aria-label="breadcrumb"] ul {
    list-style: none;
    display: flex;
    gap: 0;
    padding: 0;
    margin: 0 0 1rem;
    font-size: 0.875rem;
}
nav[aria-label="breadcrumb"] li::after {
    content: " / ";
    margin: 0 0.35rem;
    color: var(--pico-muted-color);
}
nav[aria-label="breadcrumb"] li:last-child::after {
    content: "";
}

/* Tag chips — the inline pill used for member tags and event audience tags.
 * Matches the design language of .badge but neutral-by-default (no
 * semantic status color). Lives alongside the shared chip primitives in
 * narratory-spa.css but this one is Convene-local because the tags
 * feature is Convene-only. */
.tag-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--pico-muted-border-color);
    background: var(--pico-card-background-color);
    color: var(--pico-color);
    font-size: 0.75rem;
    line-height: 1.3;
    white-space: nowrap;
    margin-right: 0.25rem;
}
.tag-chip-list {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}
.tag-chip-editable {
    cursor: pointer;
}
.tag-chip-editable:hover {
    border-color: var(--pico-primary);
}

/* Reading-width cap for member-facing public pages (community / series /
 * occurrence). Pico's .container grows to ~1450px on >=1536px viewports,
 * which makes prose unreadable. Pages opt in with
 * {% block body_class %}narrow-page{% endblock %} in base.html. Banner +
 * table + form all narrow together for a consistent reading layout. */
body.narrow-page header.container,
body.narrow-page main.container,
body.narrow-page footer.container {
    max-width: 720px;
}

/* Responsive table → card stack on narrow screens.
 * Apply to <table class="responsive-stack"> with data-label="..." on each <td>.
 * Desktop: normal table. Mobile (<576px): each <tr> becomes a card and each
 * <td> becomes a labeled line inside it. Cells whose data-label is empty
 * render the value without a label (use for trailing action cells). */
@media (max-width: 576px) {
    table.responsive-stack,
    table.responsive-stack thead,
    table.responsive-stack tbody,
    table.responsive-stack tr,
    table.responsive-stack th,
    table.responsive-stack td {
        display: block;
        width: auto;
    }
    table.responsive-stack thead {
        display: none;
    }
    table.responsive-stack tr {
        border: 1px solid var(--pico-muted-border-color);
        border-radius: var(--pico-border-radius);
        padding: 0.75rem;
        margin-bottom: 0.5rem;
    }
    table.responsive-stack td {
        border: none;
        padding: 0.25rem 0;
    }
    table.responsive-stack td[data-label]:not([data-label=""])::before {
        content: attr(data-label);
        display: block;
        font-size: 0.7rem;
        font-weight: 600;
        color: var(--pico-muted-color);
        text-transform: uppercase;
        letter-spacing: 0.03em;
        margin-bottom: 0.15rem;
    }
}

/* Markdown-rendered blocks (type descriptions/instructions, submission
   bodies): tighten default block margins so short content doesn't balloon,
   while paragraphs and lists still read as such. */
.md-block p { margin: 0 0 0.5em; }
.md-block p:last-child { margin-bottom: 0; }
.md-block ul, .md-block ol { margin: 0.25em 0 0.5em; padding-left: 1.25em; }
.md-block li { margin-bottom: 0.15em; }

/* ---------------------------------------------------------------------------
 * Recap page (pages/recap_view.html)
 *
 * The recap is a two-column reading surface: the recap prose on the left, a
 * navigational rail on the right tying it back to the community, the series,
 * and what happens next. Deliberately NOT the shared .admin-layout /
 * .admin-sidebar pair from narratory-spa.css — that is a 180px left-hand nav
 * rail with admin-dashboard semantics, and member pages are outside the SPA
 * standard's scope (see Convene AGENTS.md "Known deviations").
 * ------------------------------------------------------------------------ */
.recap-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 2rem;
    align-items: start;
}
/* min-width:0 stops a long URL or code block in the recap from blowing out
 * the grid track — the default `min-width:auto` on a grid item won't shrink. */
.recap-main { min-width: 0; }

/* The headline, podcast link and share control sit above the grid so the rail
   starts level with the recap body rather than with the title. */
/* Occurrence banner above the recap headline. Fixed aspect so a missing or
   slow image doesn't reflow the page, and object-fit so an admin upload that
   isn't 1.91:1 fills the frame without distorting. */
/* Presenter list in the recap rail. Avatars are the same 512px square JPEGs
   the agenda email uses, rendered small and round. */
.presenter-list { list-style: none; padding: 0; margin: 0; }
.presenter-list li {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
}
.presenter-list li:last-child { margin-bottom: 0; }
.presenter-meta { display: flex; flex-direction: column; min-width: 0; }
.presenter-name { font-weight: 600; }
.presenter-meta a { font-size: 0.8rem; }

.presenter-list img {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.recap-banner {
    display: block;
    width: 100%;
    aspect-ratio: 1200 / 630;
    object-fit: cover;
    border-radius: var(--pico-border-radius);
    margin-bottom: 1.25rem;
}

.recap-header { margin-bottom: 1.5rem; }

/* The rail sits alongside the recap and starts level with it. It deliberately
   does NOT scroll independently: a second scroll region beside a document the
   reader is already scrolling is a nuisance, and the rail is short enough to
   simply flow with the page. `.recap-layout` aligns both columns to start. */
.recap-rail {
    align-self: start;
}

/* A link material is labelled with its full URL, which has no spaces to break
   on — without this it overflows the column. */
.material-list a {
    overflow-wrap: anywhere;
}

.rail-card {
    background: var(--pico-card-background-color);
    border: 1px solid var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius);
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
}
.rail-card:last-child { margin-bottom: 0; }
.rail-card > h4 {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--pico-muted-color);
    margin: 0 0 0.5rem;
}
.rail-card ul { list-style: none; margin: 0; padding: 0; }
.rail-card li { margin: 0 0 0.5rem; font-size: 0.9rem; line-height: 1.4; }
.rail-card li:last-child { margin-bottom: 0; }
.rail-card p { margin: 0 0 0.5rem; font-size: 0.9rem; }
.rail-card p:last-child { margin-bottom: 0; }

/* Prev/next through a series' recaps, at the foot of the recap prose. */
.recap-pager {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 2rem;
    padding-top: 1rem;
    border-top: 1px solid var(--pico-muted-border-color);
}

@media (max-width: 768px) {
    .recap-layout { grid-template-columns: 1fr; gap: 1.5rem; }
}

/* A recap is a document people archive and print. Navigation isn't part of it. */
@media print {
    .recap-rail,
    .recap-pager,
    .recap-share { display: none !important; }
    .recap-layout { display: block; }
}

/* --- Branded links -------------------------------------------------------
 *
 * The public community / series / occurrence pages set --brand-primary and
 * --brand-secondary from the configured hex in their {% block brand_style %}.
 * Every link on those pages has to follow that hex: Pico's default #0172ad
 * collides with the brand and reads as "generic web link" in the middle of an
 * otherwise branded page. Previously each anchor opted in with an inline
 * `style="color:var(--brand-primary)"`, so any link that was added without one
 * — table cells, markdown-rendered descriptions, recap lists — silently stayed
 * blue. This makes brand colour the default instead of the exception.
 *
 * Pico's own link rule is `:where(a:not([role=button]))`, i.e. zero
 * specificity, so this wins wherever the vars are defined. Where they aren't
 * (dashboard, member pages) each var falls back to the exact Pico value it
 * replaces, so those pages are unchanged: Pico's --pico-primary-underline is
 * --pico-primary at 50% alpha, and its hover underline is the solid hover
 * colour.
 *
 * Excluded: role=button links (styled as buttons, see .cta-btn) and
 * .secondary/.contrast links, where the class is an explicit "not the primary
 * colour" choice. A page that needs white-on-gradient links still wins on
 * specificity — see `.brand-banner a` in member_event_detail.html.
 */
a:not([role=button]):not(.secondary):not(.contrast) {
    --pico-color: var(--brand-primary, var(--pico-primary));
    --pico-underline: color-mix(in srgb, var(--brand-primary, var(--pico-primary)) 50%, transparent);
}

a:not([role=button]):not(.secondary):not(.contrast):is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
    --pico-color: var(--brand-secondary, var(--pico-primary-hover));
    --pico-underline: var(--brand-secondary, var(--pico-primary-hover));
}

/* --- Next-event spotlight card -------------------------------------------
 *
 * The shared card rendered by pages/_next_event_card.html on both the series
 * page and the community page. Lives here rather than as inline styles because
 * two templates now share it — see design_standards.md §10.
 *
 * Depends on --brand-primary / --brand-secondary, which every page that
 * includes the card defines in its {% block brand_style %}.
 */
.next-event-card {
    border: 1px solid var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius);
    padding: 1rem 1.25rem;
    margin-bottom: 1.5rem;
}

.next-event-card .eyebrow {
    margin: 0 0 0.25rem;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--brand-secondary);
}

.next-event-card h3 { margin: 0 0 0.5rem; }

/* The headline and CTA are the card, not links inside prose — no underline. */
.next-event-card h3 a { text-decoration: none; }

.next-event-card .meta,
.next-event-card .phase { margin: 0 0 0.5rem; }

.next-event-card .meta,
.next-event-card .phase small { color: var(--pico-muted-color); }

.next-event-card .cta { margin: 0.75rem 0 0; }

.next-event-card .cta a {
    color: var(--brand-secondary);
    font-weight: 600;
    text-decoration: none;
}
