/* Green IO Conference Management - Custom Styles
 *
 * Design tokens are loaded from tokens.css (linked in base.html before this
 * file). Every color, font size, and spacing value MUST use var(--token-name).
 * Do NOT re-declare :root tokens here — add them to tokens.css instead.
 *
 * Migration note (Strategy B): legacy --gio-* variables are aliased in
 * tokens.css so existing rules below keep working. The 47 hardcoded hex
 * values still scattered through this file should be migrated to --color-*
 * tokens opportunistically as each section is touched.
 */

/* ============================================================
   ACCESSIBILITY — WCAG 2.4.1 skip-to-content
   ============================================================
   First focusable element on every authenticated page jumps
   straight to <main>, bypassing navbar + conference selector.
   Hidden off-canvas at rest; reveals on :focus.
   ============================================================ */
.skip-link {
    position: absolute;
    top: 0;
    left: 0;
    background: var(--color-primary-400);
    color: var(--color-text-on-primary);
    padding: var(--space-2) var(--space-4);
    z-index: 1000;
    text-decoration: none;
    font-weight: 600;
    transform: translateY(-100%);
    transition: transform 0.15s ease;
}
.skip-link:focus,
.skip-link:focus-visible {
    transform: translateY(0);
    outline: 2px solid var(--color-primary-600);
    outline-offset: 2px;
}

/* The skip-link target should not show a focus ring — the user
   already knows where they landed (they triggered it). */
main:focus {
    outline: none;
}

/* ============================================================
   TYPOGRAPHY — element defaults from the token scale
   ============================================================
   Per ui-standards skill: body text floor 16px (--font-size-base);
   labels and table-cell data may use 14px (--font-size-sm).
   ============================================================ */

/* Labels: 14px allowed (label, not body) */
label {
    font-size: var(--font-size-sm);
    margin-bottom: var(--space-1);
}

/* Inputs, selects, textareas: body text (skill rule #2).
   height: auto — Pico 2 sets an explicit height on <input> (calc'd from
   its default vertical spacing) but not on <select>; with the padding
   override below, inputs would render taller than selects on the same
   form-row (reported by Gaël on /sessions/new, 2026-06-11). Let the
   shared padding drive the height for both. */
input:not([type="checkbox"]):not([type="radio"]),
select,
textarea {
    font-size: var(--font-size-base);
    height: auto;
    padding: var(--space-2) var(--space-3);
    margin-bottom: var(--space-2);
}

/* Native <option> popup theming. Without explicit colors, Chromium falls back
   to OS-native white in the popup even when the parent <select> forces a dark
   pill (e.g. navbar conference selector → white-on-white in dark mode). Bind
   to the same Pico form-element tokens the <select> already uses so both the
   closed pill and the open popup flip together. */
select option {
    background-color: var(--pico-form-element-background-color);
    color: var(--pico-form-element-color);
}

/* Buttons: 16px body, 44px min-height (skill rule #38) */
button,
[role="button"] {
    font-size: var(--font-size-base);
    padding: var(--space-2) var(--space-4);
    min-height: var(--target-size-min);
}

/* Heading scale — 1.25 modular ratio from tokens */
h1 {
    font-size: var(--font-size-xl);
    line-height: var(--line-height-heading);
    margin-bottom: var(--space-1);
}
h2 {
    font-size: var(--font-size-lg);
    line-height: var(--line-height-heading);
    margin-top: var(--space-6);
    margin-bottom: var(--space-2);
}
h3 {
    font-size: var(--font-size-md);
    line-height: var(--line-height-heading);
    margin-bottom: var(--space-2);
}
h4 {
    font-size: var(--font-size-base);
    font-weight: 600;
    line-height: var(--line-height-heading);
    margin-bottom: var(--space-1);
}

/* Tables: keep padding compact, text at --font-size-sm (data, not body) */
table td,
table th {
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
}

/* Details/summary — label-ish */
details summary {
    font-size: var(--font-size-sm);
}

/* Main container vertical padding */
main.container {
    padding-top: var(--space-6);
    padding-bottom: var(--space-6);
}

/* ============================================================
   LAYOUT UTILITIES
   ============================================================ */

.grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.grid-3 {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1rem;
}

.grid-4 {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
}

/* ============================================================
   TOP NAVIGATION
   ============================================================ */

/* Navbar uses raw palette tokens (NOT semantic --color-bg / --color-text) so it
   stays brand-navy with light text in BOTH light and dark modes. Semantic
   tokens flip per prefers-color-scheme; raw palette tokens don't. */
.navbar {
    background-color: var(--color-neutral-900);
    border-bottom: 1px solid var(--color-neutral-700);
    padding: var(--space-3) var(--space-6);
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 100;
    /* Locks the rendered height to the design-token value used by
       sticky descendants (e.g. agenda track header) for their top offset. */
    min-height: var(--navbar-height);
    box-sizing: border-box;
}

.staging-banner {
    width: 100%;
    background-color: var(--color-error-600);
    color: var(--color-neutral-50);
    text-align: center;
    font-weight: 600;
    padding: var(--space-2) var(--space-4);
    letter-spacing: 0.02em;
}

.navbar a {
    color: var(--color-neutral-50);
    text-decoration: none;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.navbar a:hover,
.navbar a.active {
    background-color: rgba(255, 151, 71, 0.18);
    color: var(--color-primary-300);
}

.navbar .nav-links {
    display: flex;
    gap: var(--space-1);
    align-items: center;
}

.navbar .nav-separator {
    width: 1px;
    height: 1.5rem;
    background-color: rgba(255, 255, 255, 0.2);
    margin: 0 var(--space-2);
}

.navbar .nav-right {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.navbar .nav-right .user-name {
    color: var(--color-neutral-300);
    font-size: var(--font-size-sm);
}

/* Account menu — collapses the user name + logout into one icon-triggered
   dropdown so the nav bar reclaims horizontal room (e.g. for Contributors).
   Standard pattern: a user icon opens a small panel with the name header
   and the logout action. */
.navbar .user-menu {
    margin: 0;
    position: relative;
}

.navbar .user-menu > summary {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-2);
    color: var(--color-neutral-300);
}

.navbar .user-menu > summary::-webkit-details-marker { display: none; }
.navbar .user-menu > summary::after { display: none; }
.navbar .user-menu > summary:hover { color: var(--color-neutral-50); }

.navbar .user-menu > ul {
    right: 0;
    left: auto;
    min-width: 12rem;
}

.navbar .user-menu .user-menu-name {
    font-weight: 600;
    color: var(--color-text);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--color-border);
    pointer-events: none;
}

/* Scoped nav tabs greyed out when no conference is selected.
   The links stay clickable so the user can still reach a scoped route —
   they just land on the shared "pick a conference" empty state. */
.navbar a.nav-scoped-disabled {
    opacity: 0.35;
    pointer-events: auto;          /* still clickable — see above */
}

.navbar a.nav-scoped-disabled:hover {
    background-color: transparent; /* kill the orange-tint hover so disabled reads as disabled */
    opacity: 0.55;
}

.navbar a.nav-scoped-disabled.active {
    opacity: 0.7;                  /* the clicked tab stays a touch brighter so the user
                                       can see which tab they're on */
}

/* Empty state shown on every scoped page when no conference is selected */
.select-conference-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: var(--space-16) var(--space-8);
    margin: var(--space-8) 0;
    background: var(--color-bg-subtle);
    border: 2px dashed var(--gio-orange);
    border-radius: var(--radius-md);
    color: var(--color-text);
}

.select-conference-empty i {
    color: var(--gio-orange);
    margin-bottom: var(--space-3);
}

.select-conference-empty h2 {
    margin: 0 0 var(--space-2) 0;
    font-size: var(--font-size-lg);
}

.select-conference-empty p {
    max-width: 32rem;
    margin: 0;
    color: var(--color-text-secondary);
}

/* Conference selector */
.conference-selector {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.conference-selector select {
    background-color: rgba(255, 255, 255, 0.1);
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.2);
    /* Extra right padding reserves room for Pico's chevron near the right
       edge; the symmetric shorthand would otherwise let a long conference
       name run under the arrow. */
    padding: 0.4rem 1.75rem 0.4rem 0.6rem;
    border-radius: 4px;
    font-size: 0.85rem;
    margin-bottom: 0;
}

/* Highlight when the user clicked a scoped tab without a conference selected */
.conference-selector-needed select {
    background-color: var(--color-primary-400);
    color: var(--color-text-on-primary);
    border: 2px solid var(--color-primary-400);
    font-weight: 600;
    box-shadow: 0 0 0 3px rgba(255, 151, 71, 0.35);
    animation: pulse-orange 1.6s ease-in-out 0s 2;
}

.conference-selector-needed select option {
    background-color: var(--pico-form-element-background-color);
    color: var(--pico-form-element-color);
}

/* De-emphasise the "Past conferences" group: it must read as smaller than
   the still-active editions above it, not larger (browsers render an
   optgroup at their default size otherwise, inverting the hierarchy). */
.conference-selector select optgroup,
.conference-selector select optgroup option {
    font-size: 0.75rem;
}

.conference-selector-prompt {
    color: var(--gio-orange);
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
}

@keyframes pulse-orange {
    0%   { box-shadow: 0 0 0 3px rgba(245, 146, 42, 0.35); }
    50%  { box-shadow: 0 0 0 6px rgba(245, 146, 42, 0.15); }
    100% { box-shadow: 0 0 0 3px rgba(245, 146, 42, 0.35); }
}

/* ============================================================
   BREADCRUMBS
   ============================================================ */

/* Back-link: small navigation aid rendered above the breadcrumb on any
   detail page reached via ?return_to=…. NOT a primary action — visually
   muted so it sits between the page chrome and the breadcrumb without
   competing for attention with the page-header action row (Edit / kebab
   / Danger zone). See shared/_macros.html → back_link macro and
   docs/style-guide.md → "Back link (return_to navigation)". */
a.back-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    text-decoration: none;
    margin-bottom: var(--space-1);
}
a.back-link:hover {
    color: var(--color-text);
    text-decoration: underline;
}
a.back-link > i { flex-shrink: 0; }

nav.breadcrumb {
    display: block;
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    margin-bottom: var(--space-2);
}

nav.breadcrumb ul {
    display: inline;
    margin: 0;
    padding: 0;
    list-style: none;
}

nav.breadcrumb a {
    color: var(--color-text-secondary);
    text-decoration: none;
}

nav.breadcrumb a:hover {
    color: var(--gio-orange);
}

/* ============================================================
   PAGE HEADER
   ============================================================ */

/* Page header — colored 48px icon + H1 + optional actions + hairline divider.
   Rendered via the `page_header` Jinja macro in shared/_macros.html.
   The 48px icon column matches the section_rail width, so on detail pages
   that use a rail the title icon and rail icons share the same x-position
   (the rail visually hangs from the title icon). */
.page-header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: 0 0 var(--space-2);
}

.page-header__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    color: var(--gio-orange);
    flex-shrink: 0;
}

.page-header__icon i {
    width: 32px;
    height: 32px;
}

.page-header h1 {
    font-size: var(--font-size-2xl);
    line-height: var(--line-height-tight);
    margin: 0;
}

.page-header__actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.page-scope {
    color: var(--color-text-secondary);
    font-weight: 400;
    font-size: var(--font-size-lg);
}

.page-divider {
    border: 0;
    border-top: 1px solid var(--color-border);
    margin: 0 0 var(--space-6);
}

/* Footer mirror of .page-header__actions — same row of Back / Edit / Change log
   rendered at the bottom of view pages so the user does not have to scroll back
   to the top to act. Right-aligned, same gap as the top row. The footer
   divider has top margin (space above the row) instead of bottom margin
   (the top divider sits above its row). */
.page-divider--footer {
    margin: var(--space-6) 0 var(--space-4);
}

.page-footer__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-bottom: var(--space-6);
}

/* Section toolbar — heading + action button row inside a page (not the page header).
   Used on multi-section pages like /users where a sub-section has its own create
   button. Distinct from .page-header (which is a single per-page H1 component). */
.section-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin: var(--space-6) 0 var(--space-4);
}

.section-toolbar h3 {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Admin sub-navigation tabs */
.admin-tabs {
    display: flex;
    gap: 0;
    width: fit-content;
    border-bottom: 2px solid var(--color-border);
    margin-bottom: var(--space-6);
}

.admin-tabs a {
    padding: var(--space-2) var(--space-4);
    text-decoration: none;
    color: var(--color-text-secondary);
    font-weight: 500;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    transition: color 0.15s, border-color 0.15s;
}

.admin-tabs a:hover {
    color: var(--color-text);
}

.admin-tabs a.active {
    color: var(--gio-orange);
    border-bottom-color: var(--gio-orange);
}

/* ============================================================
   BUTTON GROUPS
   ============================================================ */

.button-group {
    display: flex;
    gap: 0.75rem;
    align-items: center;
}

/* Pico CSS gives <button> wider vertical padding (form-element
   spacing) than the project's button rule (--space-2) AND adds a
   default ``margin-bottom``. Both Pico rules win because of selector
   precedence, so a <button> inside a .button-group ends up taller
   than its <a role="button"> siblings and the form-element bottom
   margin shifts it up under align-items: center. Re-equalise both
   axes here so a <button> in any .button-group lines up with
   <a role="button"> siblings (e.g. the three buttons in the Speaker
   Kanban header). */
.button-group > button {
    padding-block: var(--space-2);
    margin: 0;
}

.button-group-right {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    margin-top: 1.5rem;
}

/* ----------------------------------------------------------------
   Action bar — the canonical wrapper for form footers, wizard
   footers, and any right-aligned action row of 2-4 buttons.

   Goals (from /dev/ui-action-bars review):
   - All buttons same height (min-height 44px for WCAG 2.5.5).
   - No internal label wrap (white-space: nowrap).
   - Short labels get a 7.5rem floor so a 4-char button does not
     look stunted next to a 22-char button; long labels grow to
     content.
   - Compact horizontal padding (0.5rem 1rem) — keeps the row from
     looking heavy without losing target size.
   - Pico's submit-button-stretch override (form <button> defaults
     to width:100% inside flex containers).
   - At narrow CONTAINER widths (not viewport), switch to a 2x2
     grid so 4 buttons wrap cleanly as 2+2 instead of 3+1.

   Order convention (structural-rules § Button-row ordering): lowest
   risk on the left, primary affirmative action on the right.

   Call sites use the form_footer() / wizard_footer() macros in
   shared/_macros.html; .action-bar is the rendered output.
   ---------------------------------------------------------------- */
.action-bar-host { container-type: inline-size; }

.action-bar {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.5rem;
    flex-wrap: wrap;
}

.action-bar > button,
.action-bar > a[role="button"],
.action-bar > form > button {
    white-space: nowrap;
    width: auto;
    min-width: 7.5rem;
    padding: 0.5rem 1rem;
    min-height: 44px;
    margin: 0;
    flex: 0 0 auto;
}

.action-bar > form {
    display: inline-flex;
    margin: 0;
    width: auto;
}

@container (max-width: 560px) {
    .action-bar {
        display: grid;
        grid-template-columns: 1fr 1fr;
        justify-content: stretch;
    }
    .action-bar > button,
    .action-bar > a[role="button"],
    .action-bar > form > button {
        width: 100%;
        min-width: 0;
    }
    .action-bar > form { width: 100%; }
}

/* ----------------------------------------------------------------
   Page-header action row — bug fix.

   Previously .page-header__actions had no flex-shrink:0, so a long
   <h1> (e.g. "Attendee email 2 weeks before") stole the actions'
   horizontal space and the Edit button compressed to ~60px wide,
   forcing the icon and label to stack on two lines (66px tall).
   This rule keeps the action row at its content width regardless
   of title length, and ensures each button stays on one line.
   ---------------------------------------------------------------- */
.page-header__actions {
    flex-shrink: 0;
}

.page-header__actions > a[role="button"],
.page-header__actions > button,
.page-header__actions > details > summary[role="button"] {
    white-space: nowrap;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 44px;
}

/* ----------------------------------------------------------------
   Danger zone — replaces the inline-styled bare <form> block that
   used to live under form footers for destructive actions. Visually
   sets the destructive action apart with a divider, a labelled
   header, and explanatory help text.

   Call site: the danger_zone() macro in shared/_macros.html.
   ---------------------------------------------------------------- */
.danger-zone {
    margin-top: 2rem;
    border-top: 1px solid var(--pico-muted-border-color);
    padding-top: 1rem;
}

.danger-zone__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 0.35rem;
    font-size: 0.95rem;
    color: var(--color-error, #9b1c1c);
}

.danger-zone__help {
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    color: var(--color-text-secondary);
}

.danger-zone > form {
    display: inline-block;
    margin: 0;
    width: auto;
}

.danger-zone > form > button {
    min-height: 44px;
    padding: 0.5rem 1rem;
    width: auto;
}

/* Comms landing page — inline dropdowns in page_header so the
   work surface (data_table) stays above the fold. Pico's `<details
   role="list">` provides the dropdown; we just constrain width and
   suppress the default block layout when nested in a button-group. */
.dropdown-inline {
    position: relative;
    margin: 0;
}

.dropdown-inline > summary {
    margin: 0;
    white-space: nowrap;
}

.dropdown-inline > ul {
    min-width: 14rem;
}

/* Inline result count inside the data_table toolbar so it sits next to
   the search bar / toggle and doesn't burn its own row. */
.data-table-toolbar-extra .toolbar-count {
    margin-right: 0.75rem;
    white-space: nowrap;
}

/* ============================================================
   CARDS
   ============================================================ */

.card {
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--panel-padding-sm);
    margin-bottom: var(--space-4);
}

/* Wrap a wide table that lives inside a width-capped column (e.g. a
   section card under .detail-with-rail) so it scrolls horizontally
   instead of busting past the card's right border. */
.table-scroll {
    overflow-x: auto;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
}

.card-header h3 {
    margin-bottom: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Onboarding-panel header trailing actions row (badge + workspace link). */
.ws-panel-header-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Subhead row with a trailing action button, e.g. an h4 + "Add" button
   inside a fieldset or card. Same justify-between rhythm as .card-header
   but tuned for the smaller heading. */
.subhead-with-action {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: 0.5rem;
}
.subhead-with-action > h4 { margin-bottom: 0; }

/* ============================================================
   IN-PAGE SECTION RAIL
   ============================================================
   Icon-only sticky rail for navigating sub-sections of a detail
   page (e.g. Speaker detail: Role / Person / Talks / Milestones).
   Rendered via the `section_rail` Jinja macro in shared/_macros.html.
   On viewports under 768px the rail is hidden and the page falls
   back to plain top-down scroll. */

.detail-with-rail {
    display: grid;
    /* Rail (auto) + content column capped at the readable-width token,
       so single-column blocks (cards, fieldsets, definition lists) do
       not stretch past comfortable line length. minmax(0, …) lets the
       column shrink on narrow viewports without overflowing.
       Left-aligned to match the project's form-container convention
       (no `margin: 0 auto` on inner content). */
    grid-template-columns: var(--space-12) minmax(0, var(--form-max-width));
    gap: var(--space-4);
    align-items: start;
}

/* Wide-content variant: lets the content column expand to content-max-width
   so an inner .form-mixed-width form (with a multi-pane editor) can stretch
   past --form-max-width. Pair this on the wrapper <div> when the form inside
   uses .form-mixed-width / .form-section--wide. */
.detail-with-rail--wide {
    grid-template-columns: var(--space-12) minmax(0, var(--content-max-width));
}

.section-rail {
    position: sticky;
    /* Sit just below the sticky navbar (~56px) plus breathing room. */
    top: calc(var(--space-16) + var(--space-2));
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-2);
    width: 48px;
}

.section-rail a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    color: var(--color-text-secondary);
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.section-rail a:hover,
.section-rail a:focus-visible {
    background: var(--color-bg-muted);
    color: var(--color-text);
    outline: none;
}

.section-rail a:focus-visible {
    box-shadow: 0 0 0 2px var(--color-border-focus);
}

.section-rail a i {
    width: 18px;
    height: 18px;
}

/* Numeric badge used in place of an icon when the rail item is keyed by
   position (e.g. broadcast wizard step 3 — "1", "2", "3"…). Sized to fit
   the same hit-area as the icon glyph. */
.section-rail a .rail-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-6);
    height: var(--space-6);
    border-radius: var(--radius-full);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1;
    background: var(--color-bg-muted);
    color: var(--color-text-secondary);
}

.section-rail a:hover .rail-num,
.section-rail a:focus-visible .rail-num {
    background: var(--color-surface);
    color: var(--color-text);
}

/* Anchor target offset so jump-links land below the sticky navbar
   instead of behind it. Applied to any element inside .detail-with-rail
   that has an id (the section cards). Mirrors the rail's `top` so a
   jump-target lines up with the rail's first icon. */
.detail-with-rail [id] {
    scroll-margin-top: calc(var(--space-16) + var(--space-2));
}

@media (max-width: 768px) {
    .detail-with-rail {
        grid-template-columns: 1fr;
    }
    .section-rail {
        display: none;
    }
}

/* ============================================================
   STATUS BADGES
   ============================================================
   Phase 4c: tone-token migration. Each badge maps to one of seven
   semantic tones (info / success / warning / error / neutral / sent /
   brand-fill / brand-dark). Tones flip cleanly in dark mode and all
   pairs pass WCAG AA contrast (>=4.5:1) — see MR description for the
   full ratio matrix.

   Note: --status-* tokens (still aliased in tokens.css) carry semantic
   meaning beyond color (post/email lifecycle) and are not migrated here;
   that's a separate cleanup tracked in pending.md.
   ============================================================ */

.badge {
    display: inline-block;
    padding: 0.2rem 0.6rem;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    white-space: nowrap;
}

/* ---- Tone definitions — theme-aware via semantic tokens in tokens.css.
   Dark-mode swap happens at the token layer, so each tone is one rule. ---- */
.badge-tone-info,
.badge-info,
.badge-scheduled,
.badge-considered,
.badge-brainstorm,
.badge-brainstorming,
.badge-qualification,
.badge-conversation,
.badge-invited,
.badge-planning,
.badge-draft_ready,
.badge-ready,
.badge-provisioned,
.badge-editor {
    background: var(--badge-info-bg);
    color: var(--badge-info-fg);
}

.badge-tone-success,
.badge-confirmed,
.badge-accepted,
.badge-delivered,
.badge-speakers_confirmed,
.badge-validated,
.badge-signed,
.badge-onboarded,
.badge-active,
.badge-reviewed,
.badge-posted,
.badge-confirmed_sent {
    background: var(--badge-success-bg);
    color: var(--badge-success-fg);
}

.badge-tone-warning,
.badge-maybe,
.badge-cfp_submitted,
.badge-pending,
.badge-interested,
.badge-proposal_sent,
.badge-verbal_agreement,
.badge-onboarding_in_progress,
.badge-sent_via_partner {
    background: var(--badge-warning-bg);
    color: var(--badge-warning-fg);
}

.badge-tone-error,
.badge-declined,
.badge-cfp_rejected,
.badge-not_selected,
.badge-overdue {
    background: var(--badge-error-bg);
    color: var(--badge-error-fg);
}

.badge-tone-neutral,
.badge-withdrawn,
.badge-idea,
.badge-cancelled,
.badge-skipped,
.badge-viewer,
.badge-draft,
/* ADR 021 §13.3: ARCHIVED is "we stopped pursuing without a no exchange",
   distinct from DECLINED. Renders neutral-grey, not negative-red. */
.badge-archived,
.badge-priority-low {
    background: var(--badge-neutral-bg);
    color: var(--badge-neutral-fg);
}

/* ADR 021 §13.2 — Commitment priority badges projected from
   CommitmentPriority (HIGH/MEDIUM/LOW). HIGH = warning tone (attention
   without alarm), MEDIUM = info tone, LOW = neutral (above). */
.badge-priority-high {
    background: var(--badge-warning-bg);
    color: var(--badge-warning-fg);
}
.badge-priority-medium {
    background: var(--badge-info-bg);
    color: var(--badge-info-fg);
}

/* ADR 021 §13.4 — Archived organisations get a muted row in the portfolio
   so they read as background rather than active triage targets. */
.row-archived {
    opacity: 0.6;
}

/* In-flight "sent" — kept distinct from generic info per audit spec */
.badge-tone-sent,
.badge-sent {
    background: var(--badge-sent-bg);
    color: var(--badge-sent-fg);
}

/* Brand fill — orange chip, fixed in both modes */
.badge-tone-brand-fill,
.badge-sold_out {
    background: var(--badge-brand-fill-bg);
    color: var(--badge-brand-fill-fg);
}

/* Brand dark — navy chip, fixed in both modes */
.badge-tone-brand-dark,
.badge-admin,
.badge-completed,
.badge-fulfilled,
.badge-participated {
    background: var(--badge-brand-dark-bg);
    color: var(--badge-brand-dark-fg);
}

/* ============================================================
   TABLES
   ============================================================ */

table {
    width: 100%;
}

table th {
    background-color: var(--color-bg-subtle);
    color: var(--color-text-secondary);
    font-weight: 600;
    font-size: var(--font-size-sm);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* ============================================================
   LIST SEARCH + COLUMN FILTERS (Phase 3 filter redesign)
   ============================================================ */

/* data_table macro: the optional toolbar row holds the search input on
   the left and `toolbar_extra` (e.g. a Broadcast/Direct segmented control)
   on the right. Used on /comms and /communication/templates per ADR 005 §7. */
.data-table-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
    flex-wrap: wrap;
}
.data-table-toolbar-extra {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    white-space: nowrap;
}
.data-table-toolbar .list-search {
    margin-bottom: 0;
}

/* Toolbar mailbox filter — was a nested-label cluster before audit
   finding #4. Now a borderless inline fieldset that visually matches
   the rest of the toolbar row. */
.mailbox-filter {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3, 0.75rem);
    border: 0;
    padding: 0;
    margin: 0;
}
.mailbox-filter legend {
    padding: 0;
    margin: 0;
    font-weight: normal;
    color: var(--muted-color, #4a5560);
}

.kind-toggle {
    display: inline-flex;
    border: 1px solid var(--muted-border-color, #cdd5dd);
    border-radius: var(--border-radius, 4px);
    overflow: hidden;
}
.kind-toggle__option {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.875rem;
    line-height: 1;
    color: var(--muted-color, #4a5560);
    text-decoration: none;
    background: var(--card-background-color, #fff);
}
.kind-toggle__option + .kind-toggle__option {
    border-left: 1px solid var(--muted-border-color, #cdd5dd);
}
.kind-toggle__option:hover {
    background: var(--card-sectionning-background-color, #f5f7fa);
}
.kind-toggle__option--active {
    background: var(--primary, #1B1B3A);
    color: var(--primary-inverse, #fff);
    font-weight: 600;
}
.kind-toggle__option--active:hover {
    background: var(--primary, #1B1B3A);
}

/* Bulk-select sticky action bar (ADR 005 §3 / build-order item 18).
   Pinned to the bottom of the viewport when at least one row is
   selected. Reveals via the `hidden` attribute, so display is reset
   here only when the form is visible. */
.bulk-select-bar {
    position: sticky;
    bottom: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    margin-top: var(--space-3);
    background: var(--card-background-color, #fff);
    border: 1px solid var(--muted-border-color, #cdd5dd);
    border-radius: var(--border-radius, 4px);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
    flex-wrap: wrap;
}
.bulk-select-bar[hidden] {
    display: none;
}
.bulk-select-bar__count {
    color: var(--muted-color, #4a5560);
    font-size: 0.9rem;
}
.bulk-select-bar select {
    min-width: 16rem;
    margin: 0;
}
.bulk-select-bar label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

/* Wizard progress indicator (ADR 005 §1) — 5-step horizontal pill row. */
.wizard-progress {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0;
    margin: 0 0 var(--space-3);
    list-style: none;
    flex-wrap: wrap;
}
.wizard-progress__step {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--muted-border-color, #cdd5dd);
    border-radius: 999px;
    background: var(--card-background-color, #fff);
    color: var(--muted-color, #4a5560);
    font-size: 0.875rem;
}
.wizard-progress__step--done {
    background: var(--card-sectionning-background-color, #f5f7fa);
    color: var(--muted-color, #4a5560);
}
.wizard-progress__step--current {
    background: var(--primary, #1B1B3A);
    color: var(--primary-inverse, #fff);
    border-color: var(--primary, #1B1B3A);
    font-weight: 600;
}
.wizard-progress__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5em;
    height: 1.5em;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.2);
    font-size: 0.8rem;
    font-weight: 600;
}
.wizard-progress__step:not(.wizard-progress__step--current) .wizard-progress__num {
    background: var(--muted-border-color, #cdd5dd);
    color: var(--card-background-color, #fff);
}

.list-search {
    position: relative;
    max-width: 30ch;
    margin-bottom: var(--space-3);
}

.list-search input[type="search"] {
    margin: 0;
    padding-right: 32px;
    /* Override Pico's left-side magnifier background and the padding it
       reserves for it. Pico ships a faded SVG glyph that renders as a
       grey circle behind the placeholder; we want the icon on the right
       (added in the macro), not the left. */
    padding-inline-start: var(--space-3);
    background-image: none !important;
    width: 100%;
}

/* Suppress the Webkit/Chromium native magnifier glyph and clear-button so
   the custom search icon on the right is the only adornment. Firefox
   doesn't render a built-in glyph on <input type="search">, so this is
   a no-op there. */
.list-search input[type="search"]::-webkit-search-decoration,
.list-search input[type="search"]::-webkit-search-cancel-button,
.list-search input[type="search"]::-webkit-search-results-button,
.list-search input[type="search"]::-webkit-search-results-decoration {
    display: none;
    -webkit-appearance: none;
}

.list-search-icon {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
    color: var(--color-text-secondary);
    width: 16px;
    height: 16px;
}

/* Modifier for the person-picker macro: same magnifier-glyph suppression
   and right-side icon as a list filter, but the input fills the form
   field width instead of clamping at 30ch. Keeps the base `.list-search`
   bottom margin so the following <small class="field-help"> has room for
   its negative top margin (Pico's "tight helper text" pattern). */
.list-search--picker {
    max-width: none;
}

/* Clear-search button (×) — same right-edge slot as the search icon.
   Hidden by default; data-table.js adds `.list-search--applied` to the
   wrapper when the input holds an applied (non-empty, unedited-since-
   render) value. Typing in the input removes that class, so the icon
   reappears the moment the user starts modifying the query. */
.list-search-clear {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: 0;
    margin: 0;
    padding: var(--space-1);
    min-width: 32px;
    min-height: 32px;
    cursor: pointer;
    color: var(--color-text-secondary);
    border-radius: var(--radius-sm);
    display: none;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.list-search-clear:hover,
.list-search-clear:focus-visible {
    color: var(--color-text);
    background: var(--color-bg-subtle, transparent);
}

.list-search-clear i {
    width: 16px;
    height: 16px;
}

.list-search--applied .list-search-clear {
    display: inline-flex;
}

.list-search--applied .list-search-icon {
    display: none;
}

/* Column-header filter: label + control stacked inside a <th> cell.
   Overrides the uppercase/letter-spacing applied to th by default. */
.col-filter {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    align-items: stretch;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
}

.col-filter > select,
.col-filter > .multi-select {
    font-size: var(--font-size-sm);
    text-transform: none;
    letter-spacing: 0;
    margin: 0;
    padding: var(--space-1) var(--space-2);
    width: 100%;
    min-height: auto;
}

/* Active-filter dot: light up whenever a non-empty option is selected.
   :has() drives this from the live <select> state, so the dot updates the
   instant the user changes the filter — no server round-trip needed. The
   .col-filter-active class is still emitted on initial page render for
   browsers without :has() support. */
.col-filter-active::after,
.col-filter:has(select > option[value=""]:not(:checked))::after {
    content: " •";
    color: var(--gio-orange);
    margin-left: var(--space-1);
}

/* Spreadsheet-style column header: plain label + chevron icon that opens
   a small popover (sort + filter) — like Google Sheets / Excel. The
   <th> keeps its uppercase tracking so labels still read as headers;
   the dropdown panel resets that locally. */
.col-header {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.col-label {
    /* Inherits the <th>'s uppercase/letter-spacing from Pico — leave alone.
       Keep multi-word labels (e.g. "Managed by", "Session title") on one line
       so adjacent narrow columns don't force a header to two rows. */
    white-space: nowrap;
}

/* Cell-level nowrap utility: apply on a <td> when its content (badge + help
   icon, short hyphenated tokens like "Co-Speaker", etc.) should never break
   across lines. Long-text columns (titles, descriptions) must NOT use this. */
.cell-nowrap {
    white-space: nowrap;
}

.col-menu {
    position: relative;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
    font-size: var(--font-size-sm);
}

/* Spreadsheet-style column header dropdown. Built on a button + sibling
   panel, NOT <details>/<summary> — Firefox renders the disclosure marker
   on summary even with the full kill-recipe applied, so we sidestep the
   element entirely. Open/close + click-outside is handled by data-table.js. */
.col-menu {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.col-menu-trigger {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    color: var(--color-text-secondary);
    padding: 2px var(--space-1);
    margin: 0;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    min-height: auto;
    height: auto;
}

.col-menu-trigger:hover,
.col-menu.open > .col-menu-trigger {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text);
}

.col-menu-trigger:focus-visible {
    outline: 2px solid var(--gio-orange);
    outline-offset: 2px;
}

.col-menu > summary:hover,
.col-menu[open] > summary {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text);
}

/* Active dot — lights up when the column has a sort or filter applied. */
.col-menu.col-menu-active > .col-menu-trigger::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--gio-orange);
    margin-right: 4px;
    display: inline-block;
}

.col-menu-panel {
    position: absolute;
    z-index: 20;
    top: calc(100% + 2px);
    left: 0;
    min-width: 220px;
    max-width: 320px;
    max-height: 360px;
    overflow-y: auto;
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: var(--space-1);
    box-shadow: var(--shadow-md, 0 4px 12px rgba(0,0,0,0.12));
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
    font-size: var(--font-size-sm);
}

/* Right-align the panel for the rightmost columns so it doesn't clip
   off-screen. The .col-actions <th> keeps its own width=1% slot, so the
   panel of the last data column sits comfortably aligned to the right
   edge of its <th>. */
th:nth-last-child(2) .col-menu-panel,
th:last-child .col-menu-panel {
    left: auto;
    right: 0;
}

.col-menu-item {
    appearance: none;
    background: transparent;
    border: none;
    color: inherit;
    text-align: left;
    padding: var(--space-2);
    margin: 0;
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    line-height: 1.2;
    width: 100%;
    min-height: auto;
}

.col-menu-item:hover {
    background: var(--color-bg-soft, var(--color-border));
}

.col-menu-item[aria-current="true"] {
    background: var(--gio-orange-soft, rgba(245, 146, 42, 0.12));
    color: var(--gio-orange);
}

/* Clear filter — destructive flavor of the menu item. Sits at the bottom
   of the dropdown panel below the filter section. Hidden when the column
   has no active filter (toggled by the macro via [hidden]). */
.col-menu-item-clear {
    color: var(--color-text-secondary);
}

.col-menu-item-clear:hover {
    background: var(--color-bg-soft, var(--color-border));
    color: var(--status-overdue);
}

.col-menu-panel hr {
    border: none;
    border-top: 1px solid var(--color-border);
    margin: var(--space-1) 0;
}

.col-menu-section {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
}

.col-menu-section-label {
    font-size: var(--font-size-xs, 12px);
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-1);
}

.col-multiselect-options {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 220px;
    overflow-y: auto;
}

.col-multiselect-options label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-1);
    font-weight: 400;
    cursor: pointer;
}

.col-multiselect-options input[type="checkbox"] {
    margin: 0;
}

/* Range pair (number / date / datetime) rendered as two From/To fields
   inside the dropdown panel. Each field stacks a small uppercase label
   above its input; bounds are inclusive and cross-referenced via the
   browser's native min/max validation (the macro mirrors the values). */
.col-range {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.col-range-field {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    font-weight: 400;
}

.col-range-label {
    font-size: var(--font-size-xs, 12px);
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1;
}

.col-range-field > input {
    font-size: var(--font-size-sm);
    padding: 4px 8px;
    margin: 0;
    min-height: auto;
    height: 30px;
    width: 96px;
    max-width: 100%;
    min-width: 0;
    /* Stronger border than Pico's default so the empty input is clearly
       visible against the dropdown panel's surface. */
    background: var(--pico-form-element-background-color, var(--color-surface));
    border: 1px solid var(--color-border);
    color: var(--color-text);
}

.col-range-field > input:focus {
    border-color: var(--gio-orange);
    outline: none;
}

.col-range-field > input[type="date"],
.col-range-field > input[type="datetime-local"] {
    /* Date inputs need more room for the picker glyph and the placeholder
       text "dd/mm/yyyy". */
    width: 150px;
}

.col-range-field > input:invalid {
    /* Soft cue when the cross-referenced min/max constraint rejects the
       value (e.g. user sets "to" earlier than "from"). The form still
       serialises the bad value, but the browser blocks submission. */
    border-color: var(--status-overdue);
}

/* Range error message — shown only when one of the inputs is :invalid
   (cross-referenced min/max means "to" < "from"). Uses :has() so it
   stays purely declarative. */
.col-range-error {
    display: none;
    font-size: var(--font-size-xs, 12px);
    color: var(--status-overdue);
    padding: 2px 0;
    line-height: 1.3;
}

.col-range:has(input:invalid) > .col-range-error {
    display: block;
}

.data-table-form {
    margin: 0;
}

.data-table-form .list-search {
    margin-bottom: var(--space-3);
}

/* Trailing actions column (edit/delete). Narrow and right-aligned so it
   does not steal space from data columns. */
th.col-actions,
td.col-actions {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

/* ============================================================
   DEFINITION LIST (for detail pages, replaces key-value tables)
   ============================================================ */

.detail-list {
    display: grid;
    grid-template-columns: 10rem 1fr;
    gap: 0.5rem 1rem;
    font-size: 0.9rem;
}

.detail-list dt {
    font-weight: 600;
    color: var(--color-text-secondary);
    padding: 0.3rem 0;
}

.detail-list dd {
    margin: 0;
    padding: 0.3rem 0;
}

/* Function row: the inline-flex pencil button would otherwise inflate the
   dd's line box and push the value below the dt label. Laying the dd out as
   a centered flex row keeps the value baseline-aligned with the label. */
.detail-list dd.fn-value {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-wrap: wrap;
}

/* Paired layout: two label+value pairs per row instead of one. Used when
   short, related fields read naturally side-by-side (Type+Voucher,
   Managed by+Confirmed by, Email+Country on the Speaker page).
   Falls back to a single-column stack at the small-screen breakpoint
   so labels never get crushed. A dt/dd pair carrying .detail-list__full
   spans the full width -- escape hatch for the rare long value
   (LinkedIn URL). */
.detail-list--pairs {
    grid-template-columns: 8rem 1fr 8rem 1fr;
}

.detail-list--pairs .detail-list__full {
    grid-column: 1 / -1;
}

@media (max-width: 640px) { /* css-tokens: allow */
    .detail-list--pairs {
        grid-template-columns: 10rem 1fr;
    }
    .detail-list--pairs .detail-list__full {
        grid-column: 1 / -1;
    }
}

/* ============================================================
   FORMS
   ============================================================ */

.form-container {
    max-width: 720px;
}

.form-container-wide {
    max-width: 960px;
}

/* Mixed-width form: container expands to content-max-width so an embedded
   multi-pane editor (markdown editor + live preview) can use the full
   working surface, while regular fieldsets stay capped at form-wide-max-width
   for comfortable line length. Pair `.form-mixed-width` on the <form> with
   `.form-section--wide` on the fieldset that wraps the editor.
   See structural-rules: "Primary work surfaces get full width". */
.form-mixed-width {
    max-width: var(--content-max-width);
}

.form-mixed-width > .form-section,
.form-mixed-width > .button-group-right,
.form-mixed-width > p,
.form-mixed-width > div:not(.form-section--wide) {
    max-width: var(--form-wide-max-width);
    margin-left: auto;
    margin-right: auto;
}

.form-mixed-width > .form-section--wide {
    max-width: var(--content-max-width);
    margin-left: auto;
    margin-right: auto;
}

/* Fieldset sections */
.form-section {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-4) var(--space-4) var(--space-2);
    margin-bottom: var(--space-6);
    background: var(--color-surface);
    color: var(--color-text);
}

.form-section legend {
    font-weight: 600;
    font-size: var(--font-size-sm);
    color: var(--color-text);
    padding: 0 var(--space-2);
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

/* Form grid rows (replacing old form-row/form-row-3) */
.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.form-row-3 {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1rem;
}

/* Narrow viewports: stack form-row cells. Without this, cramped columns
   wrap some labels onto two lines and not others, pushing the inputs in
   the same row out of horizontal alignment. */
@media (max-width: 640px) { /* css-tokens: allow */
    .form-row,
    .form-row-3 {
        grid-template-columns: 1fr;
    }
}

/* Force form fields inside .form-row and .form-row-3 to fill their grid
   cell. Without this, an `<input type="tel">` rendered alongside
   `<select>` siblings ends up narrower than the selects because browsers
   apply different intrinsic widths to text vs select controls. The
   wrapping `<label>` already spans its grid cell, but the child input
   does not unless explicitly told to. */
.form-row > label,
.form-row-3 > label,
.form-row > div,
.form-row-3 > div {
    min-width: 0;
}
.form-row > label input:not([type="checkbox"]):not([type="radio"]),
.form-row > label select,
.form-row > label textarea,
.form-row-3 > label input:not([type="checkbox"]):not([type="radio"]),
.form-row-3 > label select,
.form-row-3 > label textarea,
.form-row > div input:not([type="checkbox"]):not([type="radio"]),
.form-row > div select,
.form-row > div textarea,
.form-row-3 > div input:not([type="checkbox"]):not([type="radio"]),
.form-row-3 > div select,
.form-row-3 > div textarea {
    width: 100%;
    box-sizing: border-box;
}

/* Bottom-align the controls in a form row whose cells carry labels of
   differing heights (e.g. a long label that wraps to two lines next to
   short single-line labels). Each cell becomes a flex column and its
   control (the last child) is pushed to the cell's bottom, so every
   input/select/checkbox shares one baseline regardless of label height. */
.form-row-bottom > div {
    display: flex;
    flex-direction: column;
}
.form-row-bottom > div > :last-child {
    margin-top: auto;
}

/* Checkbox rendered as a labelled control inside a .form-row / .form-row-3
   cell, so it lines up with the <select>/<input> siblings on the same row.
   The field name sits in the normal label above; this control band matches
   the inputs' height (so the box is vertically centred against them) and
   carries the same bottom margin for shared baseline. */
.checkbox-as-control {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: var(--form-control-height);
    margin-bottom: var(--space-2);
    cursor: pointer;
}
.checkbox-as-control input[type="checkbox"] {
    margin: 0;
}

/* Read-only toggle for detail (view) pages: a disabled Pico switch shown
   inline with its Yes/No state, sized to sit in a detail-list <dd> row
   without the form-control height band so the row height matches its
   text-only siblings. */
.toggle-readonly {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}
.toggle-readonly input[type="checkbox"] {
    margin: 0;
}

/* Required field marker */
.required::after {
    content: " *";
    color: var(--status-overdue);
}

/* Optional section note */
.form-section-note {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    font-weight: 400;
    margin-left: var(--space-2);
}

/* Helper text under fields */
.field-help {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    margin-top: -0.5rem;
    margin-bottom: var(--space-2);
}

/* Inline sync alert under a <dd> on the Person detail page when the
   stored Person.<field> differs from the most recent role snapshot.
   Renders in-flow with the dd's text rather than as a separate block. */
.sync-alert {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    margin-left: 0.5rem;
    padding: 0.1rem 0.5rem;
    background: var(--gio-warning-bg, #fff8e1);
    color: var(--gio-warning-text, #6b4f00);
    border-radius: 0.25rem;
    font-size: 0.85em;
}
.sync-alert form,
.sync-alert .inline-form {
    display: inline;
    margin: 0;
}
.sync-alert .text-link,
.text-link {
    background: none;
    border: none;
    padding: 0;
    color: var(--color-primary, #0066cc);
    text-decoration: underline;
    cursor: pointer;
    font: inherit;
}
.sync-alert .text-link:hover,
.text-link:hover {
    text-decoration: none;
}

/* HTMX live title-availability badge (rendered by /comms/check-title and
   /direct-comms/check-title). Sits directly under the title field. */
.title-availability {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    font-weight: 600;
    padding: 0.15rem 0.55rem;
    border-radius: 10px;
    margin-top: 0.25rem;
}

.title-availability-ok {
    background: var(--badge-success-bg);
    color: var(--badge-success-fg);
}

.title-availability-clash {
    background: var(--badge-error-bg);
    color: var(--badge-error-fg);
}

/* Read-only field row (e.g., status badge shown inside an edit form) */
.field-readonly-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0 0 0.75rem 0;
}

.field-readonly-label {
    font-weight: 600;
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

.field-readonly-row .field-help {
    margin: 0;
}

/* Read-only value sitting in a form-row cell where an <input> would be:
   matches input vertical rhythm so it lines up with sibling fields. */
.field-readonly-value {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: calc(1rem * var(--line-height, 1.5) + 1.25rem);
    margin: 0;
}

.field-warning {
    color: var(--color-warning-text);
}

.field-error {
    color: var(--color-error-text);
    font-weight: 600;
}

.field-success {
    color: var(--color-success-text);
}

/* FOST coupon ticket-id discovery — click-to-fill option list. */
.coupon-ticket-options {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.coupon-ticket-option {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    width: 100%;
    text-align: left;
}

.coupon-ticket-option.is-selected {
    border-color: var(--color-success-500);
    background: var(--badge-success-bg);
}

.coupon-ticket-option__label {
    font-weight: normal;
}

/* ============================================================
   FILTER BAR
   ============================================================ */

.filter-bar {
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-4);
}

.filter-bar form {
    display: flex;
    gap: 1rem;
    align-items: end;
    margin-bottom: 0;
}

.filter-bar label {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
}

.filter-bar input,
.filter-bar select {
    margin-bottom: 0;
}

.filter-bar button {
    margin-bottom: 0;
}

.filter-bar .search-field {
    flex: 1;
}

/* ============================================================
   TOAST NOTIFICATIONS
   ============================================================ */

.toast-container {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1000;
}

.toast {
    padding: 0.75rem 1rem;
    border-radius: 6px;
    margin-bottom: 0.5rem;
    animation: slideIn 0.3s ease-out;
    max-width: 400px;
}

.toast-success { background: var(--badge-success-bg); color: var(--badge-success-fg); border-left: var(--space-1) solid var(--color-success); }
.toast-error { background: var(--badge-error-bg); color: var(--badge-error-fg); border-left: var(--space-1) solid var(--color-error); }
.toast-warning { background: var(--badge-warning-bg); color: var(--badge-warning-fg); border-left: var(--space-1) solid var(--color-warning); }
.toast-info { background: var(--badge-info-bg); color: var(--badge-info-fg); border-left: var(--space-1) solid var(--color-info); }

/* Stacked flash: when a route surfaces more than one message at once it sets a
   list payload, rendered as distinct lines instead of a run-on sentence. */
.toast-list { margin: 0; padding-left: var(--space-4); }
.toast-list li + li { margin-top: var(--space-1); }

/* External-link macro: full address as readable text + adjacent icon-only
   button that opens the link in a new tab. Used for LinkedIn URLs across
   dedup surfaces (conflict panels, warning flashes, identifier list) so
   the admin can read the slug AND clearly see the "opens externally"
   affordance — per dedup-branch UX feedback. */
.external-link { display: inline-flex; align-items: baseline; gap: 0.35rem; }
.external-link__label { font-family: var(--font-family-mono, monospace); word-break: break-all; }
.external-link__icon { display: inline-flex; align-items: center; opacity: 0.7; text-decoration: none; }
.external-link__icon:hover { opacity: 1; }

@keyframes slideIn {
    from { transform: translateX(100%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}

/* ============================================================
   EMPTY STATES
   ============================================================ */

.empty-state {
    text-align: center;
    padding: var(--space-12) var(--space-4);
    color: var(--color-text-secondary);
}

.empty-state p {
    margin-bottom: 1rem;
}

.empty-state .lucide {
    width: 48px;
    height: 48px;
    margin-bottom: 1rem;
    opacity: 0.4;
}

/* ============================================================
   HTMX LOADING
   ============================================================ */

.htmx-indicator {
    display: none;
}

.htmx-request .htmx-indicator {
    display: inline-block;
}

/* htmx 2.x adds htmx-request to the indicator element itself (not an
   ancestor) when hx-indicator is used. Both selectors are needed. */
.htmx-request.htmx-indicator {
    display: inline-block;
}

/* Block-style HTMX indicator for long-running API calls (e.g. Claude
   draft generation). Centred, larger than the inline text variant so
   the user can't miss that something is happening. */
.htmx-indicator.drafts-spinner {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-6);
    margin-top: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text-secondary);
}

.htmx-request .htmx-indicator.drafts-spinner {
    display: flex;
}

.htmx-request.htmx-indicator.drafts-spinner {
    display: flex;
}

.drafts-spinner__wheel {
    width: var(--space-8);
    height: var(--space-8);
    border: 3px solid var(--color-border); /* css-tokens: allow */
    border-top-color: var(--color-text);
    border-radius: var(--radius-full);
    animation: drafts-spinner-spin 0.9s linear infinite;
}

.drafts-spinner__label {
    font-size: 0.9375rem;
    font-weight: 500;
}

.drafts-spinner__sub {
    font-size: 0.8125rem;
    color: var(--color-text-muted, var(--color-text-secondary));
}

@keyframes drafts-spinner-spin {
    to { transform: rotate(360deg); }
}

/* ============================================================
   CONFIRMATION DIALOG (Phase 4b)
   ============================================================
   Shared <dialog> used by every <form data-confirm="..."> in place
   of the native browser confirm(). Browser handles focus trapping,
   Esc-to-close, and the backdrop. We just style it to match the
   design system in both light and dark modes.
   ============================================================ */

dialog.confirm-dialog {
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 0;
    max-width: 28rem;
    width: 90%;
    box-shadow: var(--shadow-lg);
}

dialog.confirm-dialog::backdrop {
    background: rgba(0, 0, 0, 0.5);
}

dialog.confirm-dialog > article {
    margin: 0;
    padding: var(--space-6);
    background: transparent;
    border: 0;
    box-shadow: none;
}

dialog.confirm-dialog header {
    margin: 0 0 var(--space-3);
    padding: 0;
    border: 0;
    background: transparent;
}

dialog.confirm-dialog h3 {
    margin: 0;
    font-size: var(--font-size-md);
    color: var(--color-text);
}

dialog.confirm-dialog p {
    margin: 0 0 var(--space-4);
    color: var(--color-text);
}

dialog.confirm-dialog footer {
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    justify-content: flex-end;
    margin-top: 0;
}

dialog.confirm-dialog footer button {
    margin: 0;
}

/* ============================================================
   PAGINATION
   ============================================================ */

.pagination {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    align-items: center;
    margin-top: 1rem;
}

/* Collapse the nav when it carries no children (filtered result below
   the pagination threshold). Keeps the OOB swap target in the DOM so
   later HTMX responses can replace it, without leaving an empty 1rem
   gap below the table. */
.pagination:empty {
    display: none;
    margin: 0;
}

.pagination .page-info {
    padding: var(--space-2);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
}

/* ============================================================
   TEXT UTILITIES
   ============================================================ */

.text-muted {
    color: var(--color-text-secondary);
}

.text-small {
    font-size: 0.85rem;
}

.text-right {
    text-align: right;
}

.text-danger {
    color: var(--status-overdue);
}

.text-success {
    color: var(--status-reviewed);
}

/* ============================================================
   AUTH PAGES
   ============================================================ */

.auth-container {
    max-width: 400px;
    margin: 4rem auto;
    padding: 2rem;
}

.auth-container h1 {
    text-align: center;
    color: var(--color-text);
}

.auth-logo {
    text-align: center;
    margin-bottom: 2rem;
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--gio-orange);
}

.auth-container .text-center {
    text-align: center;
}

/* OTP code input — large, spaced digits */
.otp-input {
    text-align: center;
    font-size: 1.5rem;
    letter-spacing: 0.5rem;
}

/* Inline checkbox in table rows — no margin, flex-aligned */
.inline-checkbox {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

.inline-checkbox input[type="checkbox"] {
    margin: 0;
}

/* ============================================================
   KANBAN / WORKSPACE (Speaker Sourcing)
   ============================================================ */

.kanban-board {
    display: flex;
    gap: 0.75rem;
    overflow-x: auto;
    padding-bottom: 1rem;
}

.kanban-column {
    min-width: 200px;
    flex: 1;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-3);
}

.kanban-column h4 {
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-secondary);
    margin-bottom: var(--space-2);
    display: flex;
    align-items: center;
    gap: var(--space-1);
    justify-content: flex-start;
}
.kanban-column h4 .count {
    margin-right: auto;
}

.kanban-column h4 .count {
    background: var(--color-surface);
    color: var(--color-text);
    border-radius: 10px;
    padding: 0 var(--space-2);
    font-size: var(--font-size-xs);
}

.kanban-card {
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: var(--space-2);
    margin-bottom: var(--space-2);
}

.kanban-card:hover {
    border-color: var(--gio-orange);
}

/* Compact card content: title and inter-row spacing are tightened so the
   card reads as a dense glance rather than a full paragraph block. */
.kanban-card-title {
    display: block;
    color: var(--color-text);
    text-decoration: none;
    font-size: var(--font-size-sm);
    font-weight: 600;
    line-height: 1.3;
    margin-bottom: var(--space-2);
}
.kanban-card-title:hover {
    color: var(--color-link);
    text-decoration: underline;
}

.kanban-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 0.3rem;
    margin-bottom: var(--space-1);
}

.kanban-card > p {
    margin: var(--space-1) 0 0 0;
}

.browse-past-dialog article {
    min-width: min(560px, 92vw);
    max-width: 720px;
}

.browse-past-dialog h3 {
    font-size: 1rem;
    margin: 0;
}

.browse-past-dialog #browse-past-results {
    max-height: 50vh;
    overflow-y: auto;
    margin: var(--space-3) 0;
}

.browse-speaker-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--color-border);
}

.browse-speaker-item:last-child {
    border-bottom: none;
}

/* ============================================================
   COMPACT TABLE ACTIONS (inline forms in table cells)
   ============================================================ */

.table-action-form {
    display: inline;
    margin: 0;
}

.table-action-btn {
    padding: 0.2rem 0.5rem;
    font-size: 0.8rem;
    margin: 0;
}

.table-action-select {
    display: inline;
    width: auto;
    margin: 0;
    padding: 0.15rem 0.3rem;
    font-size: 0.8rem;
}

/* Inline action group for edit/delete buttons */
.action-group {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

/* Conference form's venue dropdown + "Manage venues" icon button row.
   Inline-flex so the icon hugs the select; align-items center so the
   button doesn't drift below the baseline on tall selects. */
.venue-picker {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.venue-picker > select { flex: 1; }
.venue-picker > .btn-icon { flex-shrink: 0; }

/* Small icon button in tables (neutral) */
.btn-icon {
    padding: 0.15rem;
    margin: 0;
    background: none;
    border: none;
    color: var(--muted-color);
    cursor: pointer;
    font-size: 0.75rem;
    display: inline-flex;
    align-items: center;
    border-radius: 3px;
    text-decoration: none;
}

.btn-icon:hover {
    color: var(--color);
}

.btn-icon:focus-visible,
.btn-icon-danger:focus-visible {
    outline: 2px solid var(--gio-orange, currentColor);
    outline-offset: 2px;
}

/* Small delete/remove button in tables */
.btn-icon-danger {
    padding: 0.15rem;
    margin: 0;
    background: none;
    border: none;
    color: var(--status-overdue);
    cursor: pointer;
    font-size: 0.75rem;
    display: inline-flex;
    align-items: center;
    border-radius: 3px;
}

.btn-icon-danger:hover {
    color: var(--color-error-text);
}

/* Copy-to-clipboard button (data-copy-target). Inherits .btn-icon
   sizing/hover; on success we briefly tint the icon green to confirm. */
.copy-btn-copied {
    color: var(--status-confirmed, #16a34a) !important;
}

/* ============================================================
   DETAILS/ACCORDION (expandable sections)
   ============================================================ */

details summary {
    cursor: pointer;
    color: var(--gio-orange);
    font-size: 0.85rem;
}

details[open] > summary {
    margin-bottom: 0.5rem;
}

/* ============================================================
   SAFETY LOCK (protected form sections)
   ============================================================ */

.safety-banner {
    background: var(--badge-warning-bg);
    border: 1px solid var(--color-warning);
    border-radius: 6px;
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    font-size: 0.85rem;
    color: var(--badge-warning-fg);
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

.safety-banner ul {
    margin: 0.25rem 0 0 0;
    padding-left: 1.2rem;
}

.safety-banner ul li {
    margin-bottom: 0.15rem;
}

.safety-locked .form-section-locked-fields input,
.safety-locked .form-section-locked-fields select {
    pointer-events: none;
    opacity: 0.6;
}

.safety-locked .form-section-locked-fields {
    position: relative;
}

.btn-unlock {
    font-size: 0.8rem;
    padding: 0.3rem 0.75rem;
    background: none;
    border: 1px solid var(--color-warning);
    color: var(--badge-warning-fg);
    border-radius: 4px;
    cursor: pointer;
    white-space: nowrap;
}

.btn-unlock:hover {
    background: var(--badge-warning-bg);
}

/* ============================================================
   AI DRAFT RESULTS
   ============================================================ */

.draft-results .card {
    margin-bottom: 1rem;
}

.draft-content {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    word-break: break-word;
    padding: 0.75rem;
    font-size: 0.9rem;
    max-width: 100%;
    box-sizing: border-box;
}

/* Editable counterpart of .draft-content — used by the wizard step 3
   validated-template card and each of the 3 generated draft cards so the
   user can tweak the body before clicking "Use this version". Same
   typography as .draft-content so the textarea and the rendered view feel
   continuous. */
.draft-edit {
    width: 100%;
    box-sizing: border-box;
    font-family: var(--font-mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
    font-size: 0.9rem;
    line-height: 1.5;
    padding: 0.75rem;
    resize: vertical;
    min-height: 12rem;
}

/* Card-internal padding helper for the wizard step 3 "Use this version"
   form and the "currently selected draft" callout. */
.card-padded {
    padding: 0 0.75rem 0.75rem;
}
.card-padded-form {
    padding: 0 0.75rem 0.75rem;
}

/* Audience filter JSON preview in the event-hooks list table. */
.audience-filter-pre {
    margin: 0;
    max-width: 18rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.inline-form {
    display: inline-block;
}

/* Audit finding #13: drafts inbox edit + wizard step polish — lift the
   inline styles out so the markup stays focused. */
.detail-list-padded {
    padding: 0.75rem;
}
.action-row {
    padding: 0.75rem;
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.inline-input-form {
    display: inline-flex;
    gap: 0.5rem;
    align-items: center;
}
.inline-input-form input[type="text"] {
    min-width: 18rem;
    margin: 0;
}
.notes-footer {
    padding: 0 0.75rem 0.75rem;
}

.preview-pre {
    white-space: pre-wrap;
    padding: 0.75rem;
    background: var(--card-sectionning-background-color, #f5f7fa);
    border-radius: 4px;
    max-height: 320px;
    overflow-y: auto;
}

/* Audit #30: cap the per-message <pre> in the Conversation tab so a
   long thread doesn't push everything below it off-screen. */
.conversation-message__body {
    white-space: pre-wrap;
    max-height: 12em;
    overflow-y: auto;
}

/* ============================================================
   MULTI-SELECT DROPDOWN
   ============================================================ */

.multi-select {
    position: relative;
}

.multi-select-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.45rem 0.65rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    font-size: var(--font-size-sm);
    min-height: 2.2rem;
}

.multi-select-toggle:hover {
    border-color: var(--gio-orange);
}

.multi-select-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.multi-select-tag {
    background: var(--color-bg-muted);
    color: var(--color-text);
    border-radius: 3px;
    padding: 0.1rem 0.4rem;
    font-size: var(--font-size-sm);
}

.multi-select-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    z-index: 100;
    max-height: 200px;
    overflow-y: auto;
    margin-top: 2px;
}

.multi-select-dropdown.open {
    display: block;
}

.multi-select-dropdown label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.65rem;
    margin: 0;
    font-size: 0.85rem;
    cursor: pointer;
}

.multi-select-dropdown label:hover {
    background: var(--color-bg-muted);
}

/* Inline checkbox grid used for compact multi-pick lists (e.g. the
   Conference "Additional Languages" field). Three responsive columns,
   each cell a `.checkbox-label` so the row aligns visually with the
   rest of the form's checkbox controls. */
/* Form-styled multiselect dropdown (see multiselect_dropdown macro).
   Wraps the .col-menu pattern so the trigger looks like a Pico
   <select> instead of the slim header chevron. The dropdown panel
   itself keeps the .col-menu-panel styling. */
.form-multiselect {
    display: block;
    width: 100%;
    position: relative;
    align-items: stretch;
}

.form-multiselect-trigger {
    width: 100%;
    min-height: auto;
    background: var(--pico-form-element-background-color, var(--color-surface));
    border: var(--pico-border-width, 1px) solid var(--pico-form-element-border-color, var(--color-border));
    border-radius: var(--pico-border-radius, var(--radius-md));
    padding: var(--space-2) var(--space-3);
    /* Use --pico-form-element-color (form-input text), NOT --pico-color: on
       <button> elements Pico sets --pico-color to #fff so primary-CTA text
       reads on a coloured background, which made the selected-value label
       white-on-white in this dropdown trigger. */
    color: var(--pico-form-element-color, var(--color-text));
    font-size: var(--font-size-base);
    font-weight: 400;
    line-height: 1.5;
    text-transform: none;
    letter-spacing: 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-2);
    text-align: left;
    cursor: pointer;
    margin: 0;
}

.form-multiselect-trigger::before { content: none !important; }

.form-multiselect-trigger:hover,
.form-multiselect.open > .form-multiselect-trigger {
    background: var(--pico-form-element-background-color, var(--color-surface));
    border-color: var(--pico-form-element-active-border-color, var(--gio-orange));
    color: var(--pico-form-element-color, var(--color-text));
}

.form-multiselect-trigger:focus-visible {
    outline: 2px solid var(--gio-orange);
    outline-offset: 2px;
}

.form-multiselect-label {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.form-multiselect-label--empty {
    color: var(--color-text-secondary, var(--pico-muted-color));
}

.form-multiselect-panel {
    left: 0;
    right: 0;
    width: 100%;
    min-width: 0;
    max-width: none;
}

/* "Done" confirm row at the foot of the multiselect panel — an explicit,
   discoverable way to finish a multi-pick. Click-outside / Esc still close
   it too. The button keeps Pico's default primary styling. */
.form-multiselect-actions {
    display: flex;
    justify-content: flex-end;
    padding: var(--space-2);
    border-top: var(--pico-border-width, 1px) solid var(--color-border);
}

.form-multiselect-done {
    margin: 0;
    width: auto;
    padding: var(--space-1) var(--space-4);
    font-size: var(--font-size-sm);
}

/* Multiselect fieldset wrapper. Used when the caller passes `legend=`
   to the macro. Replaces the old <label>multiselect</label> pattern,
   which (per HTML spec) made the outer <label> hijack checkbox clicks
   into the trigger <button> — clicks were silently swallowed and the
   label never updated. Strip the default fieldset chrome so it looks
   identical to a Pico-styled <label> field. */
.form-multiselect-field {
    border: 0;
    padding: 0;
    margin: 0 0 var(--pico-spacing, var(--space-3));
    min-width: 0;
}
.form-multiselect-field > legend {
    padding: 0;
    margin: 0 0 var(--pico-spacing, var(--space-2)) 0;
    font-size: var(--pico-form-element-spacing-vertical, 1rem);
    font-weight: inherit;
    line-height: var(--pico-line-height, 1.5);
    color: inherit;
}

/* ============================================================
   WIZARD (New Comms flow)
   ============================================================ */

.wizard-choice-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
    margin: 1.5rem 0;
}

.wizard-choice-card {
    margin: 0;
}

.wizard-choice-button {
    width: 100%;
    min-height: 180px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 2rem 1.5rem;
    text-align: center;
    cursor: pointer;
}

.wizard-choice-title {
    font-size: 1.15rem;
    font-weight: 600;
}

.wizard-choice-help {
    font-size: 0.875rem;
    opacity: 0.85;
    max-width: 24ch;
    line-height: 1.35;
}

.wizard-template-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
    margin: 1rem 0;
}

.wizard-template-option {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    background: var(--color-surface);
    color: var(--color-text);
}

.wizard-template-option:hover {
    background: var(--color-bg-muted);
}

.wizard-template-option input[type="radio"] {
    margin-top: 0.25rem;
    flex-shrink: 0;
}

.wizard-template-option-body {
    flex: 1;
    min-width: 0;
}

.wizard-template-option-title {
    font-weight: 600;
    margin-bottom: 0.2rem;
}

.wizard-template-option-desc {
    font-size: 0.85rem;
    opacity: 0.8;
}

.wizard-template-option-meta {
    font-size: 0.75rem;
    opacity: 0.7;
    margin-top: 0.25rem;
}

.wizard-preview {
    background: var(--color-bg-subtle);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: var(--space-4);
    white-space: pre-wrap;
    font-family: var(--font-family-mono);
    font-size: var(--font-size-sm);
    max-height: 400px;
    overflow-y: auto;
}

.wizard-warnings {
    background: var(--color-warning-50);
    color: var(--color-warning-text);
    border: 1px solid var(--color-warning-300);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-4);
    margin: var(--space-3) 0;
    font-size: var(--font-size-sm);
}

.wizard-warnings ul {
    margin: 0.25rem 0 0 1.25rem;
    padding: 0;
}

.button-group-left {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    margin-top: 1.5rem;
}

.wizard-spacer {
    margin-top: 1.5rem;
}

form.inline-form {
    display: inline;
}

/* ============================================================
   DESTRUCTIVE TRANSITION DIALOG (reason-capture for side-exit
   state transitions — e.g. comm skipped, sponsor declined).
   Used by state_machine_intent_panel(destructive=…).
   ============================================================ */

.destructive-transition-dialog {
    max-width: 520px;
    width: 90vw;
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 0;
}

.destructive-transition-dialog article {
    margin: 0;
    padding: 1.25rem;
}

.destructive-transition-dialog header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
}

.destructive-transition-dialog header .close {
    background: transparent;
    border: none;
    font-size: 1.75rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 0.5rem;
    width: auto;
    color: var(--gio-color);
}

.destructive-transition-dialog::backdrop {
    background: rgba(0, 0, 0, 0.4);
}

/* ============================================================
   SKIPPED COMM STYLING (grey-out rows in lists)
   ============================================================ */

tr.comm-row-skipped,
tr.comm-row-skipped td {
    color: var(--color-text-tertiary);
    background-color: var(--color-bg-subtle);
}

tr.comm-row-skipped td a,
tr.comm-row-skipped td strong {
    color: var(--color-text-tertiary);
    font-weight: normal;
    text-decoration: line-through;
}

.card.skipped-note {
    border-color: var(--status-skipped);
    background: var(--color-bg-subtle);
}

/* Comms-specific status stepper styles removed: the comms detail page
   now uses the shared .state-machine-stepper / .state-machine-intent
   pattern (see _macros.html state_machine_stepper + state_machine_intent_panel
   and the conferences/detail.html Lifecycle card). */

/* ============================================================
   UTILITY CLASSES (Phase 5 — replaces 566 inline styles)
   Use these instead of inline styles per UI_PATTERNS rule #1.
   Token-driven; never use arbitrary px values in templates.
   ============================================================ */

/* Margin */
.m-0 { margin: 0; }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--space-1); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.ml-1 { margin-left: var(--space-1); }
.ml-2 { margin-left: var(--space-2); }

/* Padding */
.p-0 { padding: 0; }

/* Display & flex */
.flex-1 { flex: 1; }
.flex-shrink-0 { flex-shrink: 0; }
.form-inline { display: inline; }

/* Width */
.w-auto { width: auto; }
.w-narrow { width: 80px; max-width: 80px; }
.w-medium { width: 120px; max-width: 120px; }
.w-wide { width: 200px; max-width: 200px; }
.w-full { width: 100%; }

/* Typography */
.font-xs { font-size: var(--font-size-xs); }
.font-sm { font-size: var(--font-size-sm); }
.font-base { font-size: var(--font-size-base); }

/* --- Audit / changelog drawer --- */
.changelog-drawer {
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 6px;
    padding: var(--space-3);
    background: var(--pico-form-element-background-color);
    margin-top: var(--space-3);
}
.changelog-header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    border-bottom: 1px solid var(--pico-muted-border-color);
    padding-bottom: var(--space-2);
    margin-bottom: var(--space-2);
}
.changelog-header > h3 { flex: 1; }
.changelog-table {
    width: 100%;
    border-collapse: collapse;
    margin: 0;
    font-size: var(--font-size-sm);
    table-layout: fixed;
}
.changelog-table th,
.changelog-table td {
    padding: var(--space-1) var(--space-2);
    border-bottom: 1px dashed var(--pico-muted-border-color);
    vertical-align: middle;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.changelog-table tbody tr:last-child td { border-bottom: none; }
.changelog-table thead th {
    text-align: left;
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-secondary);
    background: var(--color-bg-subtle);
    font-weight: 600;
    border-bottom: 1px solid var(--pico-muted-border-color);
}
.changelog-table tbody tr:hover {
    background: var(--pico-form-element-background-color);
}
.changelog-table .cl-time {
    width: 13em;
    font-family: var(--font-family-mono);
    color: var(--color-text-secondary);
}
.changelog-table .cl-action { width: 12em; }
.changelog-table .cl-action .badge {
    padding: 1px 6px;
    font-size: var(--font-size-xs);
}
.changelog-table .cl-actor { width: 10em; }
.changelog-table .cl-changes code {
    font-size: 0.9em;
    background: var(--pico-code-background-color);
    padding: 0 3px;
    border-radius: 3px;
}

/* Action badges */
.badge-created { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.badge-updated { background: var(--badge-info-bg); color: var(--badge-info-fg); }
.badge-deleted { background: var(--badge-error-bg); color: var(--badge-error-fg); }
.badge-status_change,
.badge-status-change { background: var(--badge-warning-bg); color: var(--badge-warning-fg); }

/* --- Dashboard headline stats --- */
.dashboard-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-3);
    margin: var(--space-3) 0 var(--space-4);
}
/* Global view: 5 stat cards. Drop to a wider auto-fit so 5 cards lay out
   evenly on wide screens instead of stranding two cards in a half-empty
   second row. */
.dashboard-stats.dashboard-stats--five,
.dashboard-stats:has(> .stat-card:nth-child(5)) {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));  /* css-tokens: allow — minimum stat-card width, paired with grid auto-fit */
}
@media (max-width: 720px) {
    .dashboard-stats { grid-template-columns: 1fr; }
}
.voucher-usage-fold {
    margin-top: var(--space-2);
}
.voucher-usage-fold > summary {
    cursor: pointer;
    color: var(--pico-muted-color);
    font-size: var(--font-size-sm);
}
.stat-card {
    background: var(--pico-form-element-background-color);
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 6px;
    padding: var(--space-3);
}
.stat-label {
    color: var(--pico-muted-color);
    font-size: var(--font-size-sm);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    display: flex;
    align-items: center;
    gap: var(--space-1);
}
.stat-value {
    font-size: 2rem;
    font-weight: 600;
    line-height: 1.1;
    margin-top: var(--space-1);
}
.stat-yoy {
    margin-top: var(--space-1);
}
.stat-returning {
    font-size: var(--font-size-sm);
    font-weight: 400;
    color: var(--pico-muted-color);
    margin-left: var(--space-1);
    white-space: nowrap;
}

/* --- Dashboard breakdown blocks (weekly chart, ticket-type pie, voucher list) --- */
.dashboard-block {
    margin: var(--space-4) 0;
    padding: var(--space-3);
    background: var(--pico-form-element-background-color);
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 6px;
}
.dashboard-block h3 {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    margin: 0 0 var(--space-3);
    font-size: var(--font-size-md);
}
.dashboard-block-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}
@media (max-width: 960px) {
    .dashboard-block-split { grid-template-columns: 1fr; }
}
.chart-wrap {
    position: relative;
    height: 320px;
}
.chart-wrap-pie {
    height: 280px;
}
.chart-download-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    padding: 5px;
    margin: 0;
    background: transparent;
    border: none;
    cursor: pointer;
    border-radius: var(--radius-sm);
    color: var(--color-neutral-400);
    line-height: 0;
    min-height: 0;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: none;
}
.chart-download-btn:hover,
.chart-download-btn:focus {
    background: var(--color-neutral-100);
    color: var(--color-neutral-700);
    box-shadow: none;
}
.chart-download-btn:focus-visible {
    outline: 2px solid var(--color-primary-600);
    outline-offset: 2px;
}
.voucher-usage-table {
    width: 100%;
}
.voucher-usage-table th.numeric,
.voucher-usage-table td.numeric {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* --- Dashboard "Operations" roll-up (3 sub-tiles) --- */
.ops-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-3);
}
@media (max-width: 960px) {  /* css-tokens: allow — responsive breakpoint, matches .dashboard-block-split */
    .ops-grid { grid-template-columns: 1fr; }
}
.ops-tile {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    background: var(--color-bg-subtle);
}
.ops-tile__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
    font-weight: 600;
    font-size: var(--font-size-sm);
}
.ops-tile__head > span:first-child {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}
.ops-tile__hint {
    font-weight: 400;
    font-size: var(--font-size-xs);
    color: var(--color-text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ops-vol {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    margin-bottom: var(--space-2);
}
.ops-vol-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
}
.ops-vol-label {
    flex: 0 0 7.5rem;  /* css-tokens: allow — fixed label column so bars align */
    color: var(--color-text);
}
.ops-vol-count {
    flex: 0 0 3rem;  /* css-tokens: allow — fixed numeric column, right-aligned */
    text-align: right;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-secondary);
}
progress.ops-bar {
    flex: 1;
    height: var(--space-2);
    margin: 0;
    accent-color: var(--color-primary-400);
}
progress.ops-bar--proxy {
    /* Contributors row is a relationship proxy, not true completion — mute it. */
    accent-color: var(--color-neutral-400);
}
.ops-note {
    font-size: var(--font-size-xs);
    color: var(--color-text-tertiary);
    margin: var(--space-1) 0;
}
.ops-note--muted {
    font-style: italic;
}
.ops-lead {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    margin: var(--space-2) 0 0;
    font-size: var(--font-size-sm);
    font-weight: 600;
}
.ops-lead--bad { color: var(--color-error-text); }
.ops-lead--warn { color: var(--color-warning-text); }
.ops-lead--ok { color: var(--color-success-text); }

/* --- Dashboard "Attendee profiles" collapsible + pie grid --- */
details.dashboard-collapsible > summary {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--font-size-md);
    font-weight: 600;
    cursor: pointer;
}
.profile-scope {
    display: inline-flex;
    margin: 0 0 var(--space-3);
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 6px;
    overflow: hidden;
}
.profile-scope-btn {
    margin: 0;
    width: auto;
    border: 0;
    border-radius: 0;
    padding: var(--space-1) var(--space-3);
    background: var(--pico-form-element-background-color);
    /* Not var(--pico-color): Pico redefines it to primary-inverse (white)
       on button elements, which made the inactive option white-on-white. */
    color: var(--color-text);
    font-size: var(--font-size-sm);
    cursor: pointer;
}
.profile-scope-btn + .profile-scope-btn {
    border-left: 1px solid var(--pico-muted-border-color);
}
.profile-scope-btn.active {
    background: var(--pico-primary);
    color: var(--pico-primary-inverse);
}
.profile-unspecified-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: max-content;
    margin: 0 0 var(--space-3);
    font-size: var(--font-size-sm);
    cursor: pointer;
}
.profile-unspecified-toggle input[role="switch"] {
    margin: 0;
}
.year-filter-form {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}
.year-filter-label {
    font-size: var(--font-size-sm);
    color: var(--pico-muted-color);
    margin: 0;
    white-space: nowrap;
}
.year-filter-select {
    width: auto;
    min-width: 130px;
    margin: 0;
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
    height: auto;
}
.profile-charts-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}
@media (max-width: 960px) {
    .profile-charts-grid { grid-template-columns: 1fr; }
}
.profile-chart h4 {
    margin: 0 0 var(--space-2);
    font-size: var(--font-size-sm);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--pico-muted-color);
}

/* --- Classifications admin --- */
.fc-apply {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.fc-apply p,
.fc-apply form { margin: 0; }
.fc-apply button { margin: 0; width: auto; }
.prompt-preview {
    white-space: pre-wrap;
    font-size: var(--font-size-sm);
    max-height: 320px;
    overflow-y: auto;
    background: var(--pico-code-background-color);
    padding: var(--space-2);
    border-radius: 6px;
    margin-bottom: var(--space-3);
}
/* Compact review table — one tight line per job title. */
.review-table td,
.review-table th {
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
}
/* Category-definition forms inside the collapsed "Category definitions" panel. */
.fc-def {
    margin-top: var(--space-3);
}
.fc-def textarea {
    margin-bottom: var(--space-1);
}

/* --- Admin / config options TOC --- */
.config-toc {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3) var(--space-3);
}
.config-toc-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 4px 10px;
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 4px;
    text-decoration: none;
    font-size: var(--font-size-sm);
    color: var(--pico-color);
    background: var(--pico-form-element-background-color);
}
.config-toc-link:hover {
    background: var(--pico-secondary-background);
    text-decoration: none;
}

/* ============================================================
   IMAGE UPLOAD WIDGET
   ============================================================
   Speaker profile pictures and sponsor logos. Rendered by the
   `image_slot` / `logo_tabs` macros in shared/_macros.html.
   The widget is content-width — never a full-bleed band. The
   preview swatch (light/dark) is the logo's TARGET background
   and stays fixed regardless of the page colour scheme. */

.image-slot {
    width: fit-content;
    max-width: 100%;
    margin-bottom: var(--space-4);
}

.image-slot__row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.image-slot__frame {
    flex: 0 0 auto;
    width: 120px;
    height: 120px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.image-slot__frame--light { background: #ffffff; }
.image-slot__frame--dark { background: var(--color-neutral-900); }

.image-slot__img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    cursor: zoom-in;
}

.image-slot__empty { color: var(--color-text-tertiary); }

.image-slot__controls {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--space-2);
}

/* Flatten the upload <form> so its <label> + busy span become direct
   flex children of __controls. Otherwise the form's inline line-box
   descent pushes the pick button below the other action buttons. */
.image-slot__controls > form { display: contents; }

/* The file input is hidden; the label is the visible styled trigger.
   Picking a file submits the enclosing form immediately (hx-trigger=change). */
.image-slot__pick {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-height: var(--target-size-min);
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    line-height: 1;
}

.image-slot__pick:hover { background: var(--color-bg-muted); }

.image-slot__pick:focus-within {
    outline: 2px solid var(--color-border-focus);
    outline-offset: 2px;
}

.image-slot__pick input { display: none; }

.image-slot__remove,
.image-slot__download,
.image-slot__copy {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--target-size-min);
    height: var(--target-size-min);
    margin: 0;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    color: var(--color-text-secondary);
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
}

.image-slot__pick { margin: 0; }

.image-slot__download:hover,
.image-slot__copy:hover { color: var(--color-text); background: var(--color-bg-muted); }

.image-slot__remove { color: var(--color-error-text); }
.image-slot__remove:hover { background: var(--color-bg-muted); }

.image-slot__copy.copy-btn-copied { color: var(--color-success-text); }

.image-slot__busy {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
}

/* Inline validation / warning messages — compact, not full-width toasts. */
.image-slot__msg {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    max-width: 60ch;
    margin-top: var(--space-2);
    margin-bottom: 0;
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    border-radius: var(--radius-sm);
}

.image-slot__msg i { flex: 0 0 auto; margin-top: 2px; }

.image-slot__msg--error {
    color: var(--color-error-text);
    background: var(--color-error-50);
}

.image-slot__msg--warning {
    color: var(--color-warning-text);
    background: var(--color-warning-50);
}

/* Compact variant — round headshot for speaker / person page headers. */
.image-slot--compact .image-slot__frame {
    width: 96px;
    height: 96px;
    border-radius: var(--radius-full);
}

.image-slot--compact .image-slot__img { width: 100%; height: 100%; object-fit: cover; }

/* ---- Sponsor logo tabbed frame ---- */

.logo-tabs { margin-top: var(--space-1); }

/* Radios drive the tab state. Kept in the DOM (focusable, and arrow-key
   navigable as a native radio group) but visually removed. */
.logo-tabs__radio {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.logo-tabs__nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--space-4);
}

.logo-tabs__tab {
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    cursor: pointer;
    border: 1px solid transparent;
    border-bottom: none;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.logo-tabs__tab:hover { background: var(--color-bg-muted); }

.logo-tabs__panel { display: none; }

/* Show the panel + highlight the tab matching the checked radio. */
.logo-tabs__radio:nth-of-type(1):checked ~ .logo-tabs__panels .logo-tabs__panel:nth-of-type(1),
.logo-tabs__radio:nth-of-type(2):checked ~ .logo-tabs__panels .logo-tabs__panel:nth-of-type(2),
.logo-tabs__radio:nth-of-type(3):checked ~ .logo-tabs__panels .logo-tabs__panel:nth-of-type(3),
.logo-tabs__radio:nth-of-type(4):checked ~ .logo-tabs__panels .logo-tabs__panel:nth-of-type(4) {
    display: block;
}

.logo-tabs__radio:nth-of-type(1):checked ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(1),
.logo-tabs__radio:nth-of-type(2):checked ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(2),
.logo-tabs__radio:nth-of-type(3):checked ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(3),
.logo-tabs__radio:nth-of-type(4):checked ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(4) {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text);
    font-weight: 600;
}

/* Keyboard focus indicator on the active tab label. */
.logo-tabs__radio:nth-of-type(1):focus-visible ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(1),
.logo-tabs__radio:nth-of-type(2):focus-visible ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(2),
.logo-tabs__radio:nth-of-type(3):focus-visible ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(3),
.logo-tabs__radio:nth-of-type(4):focus-visible ~ .logo-tabs__nav .logo-tabs__tab:nth-of-type(4) {
    outline: 2px solid var(--color-border-focus);
    outline-offset: -2px;
}

/* ---- Shared image lightbox (double-click any preview to enlarge) ---- */

.image-lightbox {
    border: 0;
    padding: 0;
    background: transparent;
    max-width: 92vw;
    max-height: 92vh;
    overflow: visible;
}

.image-lightbox::backdrop { background: rgba(1, 12, 52, 0.85); }

.image-lightbox__img {
    display: block;
    max-width: 92vw;
    max-height: 92vh;
    object-fit: contain;
    border-radius: var(--radius-md);
    /* Checkerboard so transparency is visible when inspecting a logo. */
    background-color: #ffffff;
    background-image:
        linear-gradient(45deg, var(--color-neutral-200) 25%, transparent 25%),
        linear-gradient(-45deg, var(--color-neutral-200) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--color-neutral-200) 75%),
        linear-gradient(-45deg, transparent 75%, var(--color-neutral-200) 75%);
    background-size: 20px 20px;
    background-position: 0 0, 0 10px, 10px -10px, -10px 0;
}

.image-lightbox__close {
    position: absolute;
    top: calc(-1 * var(--space-3));
    right: calc(-1 * var(--space-3));
    width: var(--target-size-min);
    height: var(--target-size-min);
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: var(--radius-full);
    background: var(--color-neutral-50);
    color: var(--color-neutral-900);
    cursor: pointer;
    box-shadow: var(--shadow-md);
}

/* ============================================================================
   Lifecycle stepper + intent panel
   ============================================================================
   Domain-agnostic stepper + intent panel for any state-machine-governed
   record (Conference lifecycle, Comms status, ...). The macro injects
   `--steps: N` so the same grid works for a 4-step comms flow and a
   7-step conference lifecycle. See `state_machine_stepper` and
   `state_machine_intent_panel` in _macros.html.
   ============================================================================ */

.state-machine-stepper {
    list-style: none;
    padding: 0;
    margin: var(--space-4) 0 var(--space-2);
    display: grid;
    grid-template-columns: repeat(var(--steps, 7), 1fr);
    gap: 0;
}

.state-machine-step {
    position: relative;
    text-align: center;
    padding-top: 22px;
    font-size: 11px;
    line-height: 1.3;
    color: var(--color-text-tertiary);
}

/* Connector line between dots — drawn as a ::before that spans the cell. */
.state-machine-step::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 6px;
    height: 2px;
    background: var(--color-border-strong);
}
.state-machine-step:first-child::before { left: 50%; }
.state-machine-step:last-child::before  { right: 50%; }

.state-machine-step__dot {
    position: absolute;
    left: 50%;
    top: 0;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--color-surface);
    border: 2px solid var(--color-border-strong);
    transform: translateX(-50%);
}

.state-machine-step__label {
    display: inline-block;
    padding: 0 4px;
}

.state-machine-step--done {
    color: var(--color-text-secondary);
}
.state-machine-step--done::before {
    background: var(--color-success-500);
}
.state-machine-step--done .state-machine-step__dot {
    background: var(--color-success-500);
    border-color: var(--color-success-500);
}

.state-machine-step--current {
    color: var(--color-info-600);
    font-weight: 600;
}
.state-machine-step--current .state-machine-step__dot {
    background: var(--color-info-500);
    border-color: var(--color-info-500);
    box-shadow: 0 0 0 4px var(--color-info-50);
}

/* The "done" connector on the left of the current step is already drawn
   by the previous step's ::before (its right half), so the current step's
   own ::before stays grey for the upcoming side. No extra rule needed. */

/* Meta row: reads left-to-right as "Stage X of N · Current state: BADGE
   ... → [next action]". The intent panel sits at the right edge of the
   same row so the eye doesn't jump to a new block to find the CTA. */
.state-machine-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    flex-wrap: wrap;
    margin: var(--space-2) 0 var(--space-3);
    color: var(--color-text-secondary);
    font-size: 14px;
}

/* Intent panel — inline group of action buttons that lives inside
   .state-machine-meta. The first transition is the primary CTA;
   alternates are outline; the back-edge button (if any) sits at the
   right edge of its own group. No standalone card chrome — visual
   grouping comes from the meta row. */
.state-machine-intent__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
}

.state-machine-intent__action {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

/* The shared `.table-action-form` wrapper inside each action carries Pico's
   default form margin-bottom; zero it so the row stays tight. Buttons inside
   the panel also lose Pico's bottom margin for the same reason. */
.state-machine-intent__action form,
.state-machine-intent__action button { margin: 0; }

/* Small button size utility. Tightens Pico's default (50px tall, 12/16
   padding, 16px bottom margin) so it fits in tight rows like the intent
   bar. Selectors match Pico's own `button` / `[role="button"]` at equal
   or higher specificity, so source order wins without `!important`. */
button.btn-sm,
input[type="submit"].btn-sm,
[role="button"].btn-sm {
    padding: 6px 12px;
    height: auto;
    font-size: 13px;
    line-height: 1.2;
    margin: 0;
}

/* Back action gets pushed to the right edge on wide viewports. On
   narrow widths it wraps naturally and sits at the end of the row. */
.state-machine-intent__action--back {
    margin-left: auto;
}

/* Info icon button: visually quiet, sits flush against its sibling
   submit button. Hover + focus give it a subtle backdrop. */
.state-machine-intent__info {
    background: transparent;
    border: none;
    padding: 4px;
    border-radius: var(--radius-sm);
    color: var(--color-text-tertiary);
    cursor: pointer;
    line-height: 0;
    display: inline-flex;
    align-items: center;
}
.state-machine-intent__info:hover,
.state-machine-intent__info:focus-visible {
    background: var(--color-info-100);
    color: var(--color-info-700);
}

/* Native HTML popover: anchored visually by the info icon. */
.state-machine-intent__popover {
    max-width: 320px;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-md);
    font-size: 13px;
    color: var(--color-text-secondary);
}

.state-machine-intent__popover-head {
    margin-bottom: var(--space-2);
}

/* "More actions" dropdown panel — wider than the info popovers because it
   holds vertically-stacked transition buttons with their effect bullets. */
.state-machine-intent__more-panel {
    max-width: 360px;
    padding: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-md);
    font-size: 13px;
    color: var(--color-text-secondary);
}

.state-machine-intent__more-item {
    display: block;
    margin: 0 0 var(--space-3) 0;
}
.state-machine-intent__more-item:last-of-type { margin-bottom: var(--space-2); }

.state-machine-intent__more-effects {
    margin: var(--space-1) 0 0;
    padding-left: var(--space-4);
    color: var(--color-text-tertiary);
    font-size: 12px;
    list-style: disc;
}
.state-machine-intent__more-effects li { margin: 2px 0; }

.state-machine-intent__more-hint {
    display: block;
    margin-top: var(--space-1);
    color: var(--color-text-tertiary);
    font-size: 12px;
}

/* Hairline that visually splits forward alternates from the back-edge. */
.state-machine-intent__more-divider {
    height: 1px;
    background: var(--color-border);
    margin: var(--space-2) 0 var(--space-3);
}

.state-machine-intent__effects {
    margin: var(--space-1) 0 var(--space-2);
    padding-left: var(--space-4);
    color: var(--color-text-secondary);
}
.state-machine-intent__effects li { margin: 2px 0; }

.state-machine-intent__note {
    display: block;
    color: var(--color-text-tertiary);
    font-size: 12px;
}

/* === Field tip popover ======================================================
   Icon-button (?) rendered next to a form <label> that opens a native HTML
   popover with rich, interactive content (links allowed). Pattern mirrors
   .state-machine-intent__popover above.

   Trigger: .field-tip__trigger — small icon button, transparent at rest
   Panel:   .field-tip__popover — uses the native [popover] attribute, so the
            browser handles open/close, Esc, click-outside, and top-layer
            rendering. No JS required.

   Distinct from .field-help (inline helper/error text under an input).
   See macros field_tip() in shared/_macros.html.
=========================================================================== */
.field-tip__trigger {
    background: none;
    border: 0;
    padding: var(--space-1);
    margin: 0 0 0 var(--space-1);
    /* Override Pico's button min-height so the trigger doesn't inflate
       the label's line box. The 1em x 1em sizing below satisfies WCAG
       2.5.8 AA for inline interactive content. */
    min-height: 0;
    min-width: 0;
    height: 1.5em;
    width: 1.5em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-tertiary);
    cursor: help;
    border-radius: var(--radius-sm);
    vertical-align: middle;
    line-height: 0;
}
.field-tip__trigger:hover,
.field-tip__trigger:focus-visible {
    color: var(--color-primary-600);
    background: var(--color-bg-subtle);
}
.field-tip__trigger:focus-visible {
    outline: 2px solid var(--color-primary-600);
    outline-offset: 2px;
}

.field-tip__popover {
    max-width: 320px;  /* css-tokens: allow — matches state-machine-intent popover convention */
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-md);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-body);
    color: var(--color-text);
}
.field-tip__popover a {
    text-decoration: underline;
    color: var(--color-link);
}
.field-tip__popover p:last-child,
.field-tip__popover ul:last-child {
    margin-bottom: 0;
}

/* Override the inline-form-row form-element height floor — the help
   trigger is decorative, not a form control. Match the surrounding
   text height so the label baseline aligns with sibling labels.

   A11y note: at 1em x 1em the trigger sits below the WCAG 2.5.5 and
   2.5.8 target-size minimums. Accepted trade-off in dense admin rows;
   keyboard activation (Tab + Enter) remains a full alternative. */
.inline-form-row .field-tip__trigger {
    height: 1em;
    width: 1em;
    padding: 0;
}

/* === Status-help popover (ADR 014 §9 Phase 7) =============================
   Used by templates/_macros/status_help.html. Trigger reuses
   .field-tip__trigger; the popover panel adds spacing tweaks for the
   "meaning + bulleted transitions" structure (vs field_tip's free-form
   block content).
=========================================================================== */
.status-help__popover {
    /* Reset inherited text-transform/letter-spacing: the popover can render
       inside an uppercased container (e.g. the kanban column <h4>). Help copy
       must read in normal sentence case. */
    text-transform: none;
    letter-spacing: normal;
}
.status-help__popover .status-help__meaning {
    margin: 0 0 var(--space-2);
    font-weight: var(--font-weight-medium);
}
.status-help__popover .status-help__transitions {
    margin: 0;
    padding-left: var(--space-4);
    font-size: var(--font-size-sm);
}
.status-help__popover .status-help__transitions li {
    margin-bottom: var(--space-1);
}
.status-help__popover .status-help__transitions li:last-child {
    margin-bottom: 0;
}

/* === Kanban drag-and-drop guard (ADR 014 §9 Phase 7) ====================
   Read-only columns (SCHEDULED, DELIVERED) reject drops from other
   columns; we still want them to be visible drop targets so the
   tooltip fires. .kanban-column--readonly is the marker class; the
   .kanban-column--drag-reject state class is toggled by JS during
   dragover when the source status can't legally land here.
=========================================================================== */
.kanban-column--readonly {
    background-image: linear-gradient(
        135deg,
        transparent 0%, transparent 49%,
        var(--color-border) 49%, var(--color-border) 51%,
        transparent 51%, transparent 100%
    );
    background-size: 8px 8px;  /* css-tokens: allow — diagonal-stripe pattern repeat, not a spacing rhythm */
}
.kanban-column--readonly h4 {
    color: var(--color-text-secondary);
}
/* dragstart paint: persists for the whole drag operation so the user
   sees at a glance which columns are legal targets and which aren't.
   Refined to --drag-accept / --drag-reject (the hover-intensified
   variants below) for the column currently under the pointer. */
.kanban-column--drop-valid {
    outline: 2px dotted var(--color-success-600);
    outline-offset: -2px;
}
.kanban-column--drop-invalid {
    outline: 2px solid var(--color-error-600);
    outline-offset: -2px;
    opacity: 0.7;
}
.kanban-column--drag-reject {
    outline: 2px solid var(--color-error-600);
    outline-offset: -2px;
    cursor: not-allowed;
}
.kanban-column--drag-accept {
    outline: 2px dotted var(--color-success-600);
    outline-offset: -2px;
    background-color: var(--color-success-50);
}
.kanban-card[draggable="true"] {
    cursor: grab;
}
.kanban-card.kanban-card--dragging {
    opacity: 0.4;
}

/* === Agenda overview drop-target guidance (ADR 018 §5) =================
   Mirrors the kanban tokens above — same green/red palette so the
   language is consistent across the app. Painted at dragstart on every
   row + every anchor based on placement_matrix; --drag-accept /
   --drag-reject are the hover-intensified variants for the target the
   pointer is currently over.
=========================================================================== */
.agrid-row--drop-valid,
.agrid-anchor--drop-valid {
    outline: 2px dotted var(--color-success-600);
    outline-offset: -2px;
}
.agrid-row--drop-invalid,
.agrid-anchor--drop-invalid {
    outline: 2px solid var(--color-error-600);
    outline-offset: -2px;
    opacity: 0.7;
}
.agrid-row--drag-accept,
.agrid-anchor--drag-accept {
    outline: 2px dotted var(--color-success-600);
    outline-offset: -2px;
    background-color: var(--color-success-50);
}
.agrid-row--drag-reject,
.agrid-anchor--drag-reject {
    outline: 2px solid var(--color-error-600);
    outline-offset: -2px;
    cursor: not-allowed;
}

/* === Anchor-hosted sessions strip (ADR 018 §3) =========================
   Single cross-track band rendered directly below each anchorbar, NOT
   per track (anchors are cross-track per ADR 017 §3). Each chip carries
   the hosted Session's title, optional sub-window, an edit pencil, and
   an unschedule button — same affordances as a regular row.
=========================================================================== */
.agrid-anchor-hosts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    margin: calc(var(--space-2) * -1) 0 var(--space-2);
    background-color: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-top: 0;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
}
.agrid-anchor-host {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-2);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
}
.agrid-anchor-host-title {
    font-weight: 600;
}
.agrid-anchor-host-sub {
    white-space: nowrap;
}

/* === Format-mismatch reconciliation modal (ADR 018 §6) =================
   Rendered server-side as the 409 response body when the assign endpoint
   detects a slot_type mismatch. Inserted into the DOM by the agenda
   DnD script; opens with `open` attribute.
=========================================================================== */
.format-mismatch-dialog[open] {
    position: fixed;
    inset: 0;
    z-index: 1000;
}
.format-mismatch-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: var(--space-3) 0;
}
.format-mismatch-options form {
    margin: 0;
    padding: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-subtle);
}
.format-mismatch-options form > * + * {
    margin-top: var(--space-2);
}
.format-mismatch-advanced summary {
    cursor: pointer;
    font-size: var(--font-size-sm);
}
.kanban-card__submitted-at {
    display: block;
    color: var(--color-text-tertiary);
    font-size: var(--font-size-xs);
    margin-bottom: var(--space-1);
}

/* Admin-only kebab on CONFIRMED cards. Anchored top-right within the
   card; the JS toggles draggable=false on mousedown so a click that
   starts on the kebab doesn't initiate a drag. */
.kanban-card {
    position: relative;
}
.kanban-card__kebab {
    position: absolute;
    top: var(--space-1);
    right: var(--space-1);
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--color-text-secondary);
    cursor: pointer;
}
.kanban-card__kebab:hover {
    background: var(--color-bg-subtle);
    border-color: var(--color-border);
    color: var(--color-text);
}


.state-machine-terminal {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-secondary);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin: var(--space-2) 0 0;
    font-size: 14px;
}

/* Narrow viewports: same grid, but cells are allowed to shrink and the
   stepper scrolls horizontally if labels would overlap. */
@media (max-width: 720px) {
    .state-machine-stepper {
        overflow-x: auto;
        grid-template-columns: repeat(var(--steps, 7), minmax(80px, 1fr));
    }
}

/* ============================================================================
   AGENDA OVERVIEW
   ============================================================================ */

/* --- Day -> Track collapsible hierarchy -------------------------------- */

/* Day band: top-level <details> per ConferenceDay. The summary acts as a
   sticky-ish band so scanning a packed agenda stays anchored. */
.agenda-day {
    margin-bottom: 1.25rem;
}
.agenda-day-summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    background: var(--color-neutral-100);
    border-left: 4px solid var(--color-primary-400);
    border-radius: 4px;
    list-style: none;
    user-select: none;
}
.agenda-day-summary::-webkit-details-marker { display: none; }
.agenda-day-summary::marker { display: none; }
.agenda-day-title { display: inline-flex; align-items: baseline; gap: 0.4rem; flex: 1; }
.agenda-day-meta { white-space: nowrap; }
.agenda-day[open] > .agenda-day-summary { margin-bottom: 0.5rem; }

/* Track card: nested <details> with the existing .card chrome. The
   summary replaces the old .card-header. */
.agenda-track {
    margin: 0 0 0.75rem 1.25rem;  /* indent under the day band */
}
.agenda-track-summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    list-style: none;
    user-select: none;
}
.agenda-track-summary::-webkit-details-marker { display: none; }
.agenda-track-summary::marker { display: none; }
.agenda-track-summary h3 { flex: 1; margin: 0; display: inline-flex; align-items: center; gap: 0.35rem; }

/* Chevron rotates from > to v when the details is open. */
.agenda-chevron { transition: transform 0.15s ease; flex-shrink: 0; }
details[open] > summary > .agenda-chevron { transform: rotate(90deg); }

/* Inline clickable meta in the track header (deck / tools chips). Renders
   like .text-muted .text-small but is a real <button> so keyboard + a11y
   work; the existing inline `event.stopPropagation()` prevents clicks from
   collapsing the parent <details>. */
.agenda-meta-chip {
    background: none;
    border: 0;
    padding: 0;
    margin: 0 0 0 0.5rem;
    font: inherit;
    color: var(--muted-color, currentColor);
    /* Match .text-small (0.85rem) so the room "| Name (pax)" meta and the
       Deck / Tools chips render at the same size in the track summary. */
    font-size: 0.85rem;
    cursor: pointer;
    line-height: inherit;
}
.agenda-meta-chip:hover { color: var(--color); text-decoration: underline; }
.agenda-meta-chip:focus-visible {
    outline: 2px solid var(--gio-orange, currentColor);
    outline-offset: 2px;
}

/* Inline pairing of a field control with a side-action icon (e.g. the
   "Manage rooms" cog next to the Room <select> on the add/edit-track
   forms). Stays on a single row — the inline-form parent would otherwise
   let the icon wrap below the control. */
.field-with-action {
    display: flex;
    flex-wrap: nowrap;
    align-items: end;
    gap: 0.25rem;
}

/* Agenda add/edit forms variant of .inline-form. Wraps to a second row
   on narrow viewports (matching the slot-edit form which has the most
   fields) rather than horizontal-scrolling — feedback from Gaël, 2026-06-01.

   Forces display: flex (with !important) because `form.inline-form` at
   the bottom of this file sets `display: inline` for legacy
   flash-message forms — that rule wins against `.inline-form { display:
   flex }` on element-tag specificity and would otherwise leave the
   children stacked. */
.inline-form-row {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: flex-end;
    gap: 0.75rem;
}
.inline-form-row > div { flex: 0 0 auto; position: relative; }

/* Help text anchored beneath a field inside .inline-form-row.
   `position: absolute` keeps it visually attached to its field but
   removes it from the flex sizing — otherwise it would add height to
   the field's <div>, pushing the input above the other inputs'
   shared baseline (align-items: flex-end aligns each item's bottom).
   `:has()` reserves vertical space below the row so the floating
   helper doesn't overlap whatever sits beneath it. */
.inline-form-row-help {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 0.25rem;
    max-width: 48ch;
    white-space: normal;
    line-height: 1.3;
    color: var(--muted-color, inherit);
}
.inline-form-row:has(> div > .inline-form-row-help) {
    padding-bottom: 1.75rem;
}

/* Bottom-align every control with the action-group buttons on the same row.
   Pico applies margin-bottom: var(--pico-spacing) to every form control;
   with align-items: flex-end that margin pushes the visible edge of inputs
   ABOVE the visible edge of buttons, and inputs vs buttons end up at
   different heights. Zero the bottom margins inside .inline-form-row, give
   every control the same height, and the field labels stay above their
   controls while the controls themselves sit on a single shared baseline
   with the Add/Save/Cancel buttons. Reported by Gaël on the agenda page,
   2026-06-01 ("4th time I asked"). */
.inline-form-row input:not([type="checkbox"]):not([type="radio"]),
.inline-form-row select,
.inline-form-row textarea,
.inline-form-row button,
.inline-form-row [type="submit"],
.inline-form-row .action-group {
    margin-bottom: 0;
}
.inline-form-row input:not([type="checkbox"]):not([type="radio"]),
.inline-form-row select,
.inline-form-row button,
.inline-form-row [type="submit"] {
    height: 44px;       /* matches button min-height (WCAG target size) so
                           inputs and buttons render at the same height */
    box-sizing: border-box;
    line-height: 1.2;
}
.inline-form-row label {
    display: block;
    margin-bottom: 0.25rem;
}

/* Field-width utilities so the agenda forms stay compact without each
   call site re-declaring inline styles. `field-med` ~24ch for titles /
   names / links; `field-time` matches a time input. */
.field-med  { max-width: 24ch; width: 24ch; }
.field-time { max-width: 10ch; width: 10ch; min-width: 6rem; }

/* Inset panel that hangs under the track summary — used for the per-track
   deck and interactive-tools management blocks. Sits with the track
   metadata, not at the bottom of the day. */
.field-with-action > select,
.field-with-action > input { margin-bottom: 0; }

/* Inset panel that hangs under the track summary — used for the per-track
   deck and interactive-tools management blocks. Sits with the track
   metadata, not at the bottom of the day. */
.track-side-panel {
    margin: 0.5rem 0.75rem 0.75rem 0.75rem;
    padding: 0.5rem 0.75rem;
    background: var(--color-bg-subtle, transparent);
    border-left: 2px solid var(--color-border, currentColor);
    border-radius: 4px;
}
.track-side-panel > h4 {
    margin: 0 0 0.5rem 0;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* --- Compact slot rows -------------------------------------------------- */

/* Tighter padding than Pico's default; agenda rows must stay scannable
   even with 10+ slots per track. */
.agenda-slots th,
.agenda-slots td {
    padding: 0.3rem 0.5rem;
    vertical-align: middle;
    line-height: 1.25;
}
.agenda-slots .slot-time { white-space: nowrap; font-variant-numeric: tabular-nums; }
.agenda-slots .slot-title strong { margin-right: 0.25rem; }
.agenda-slots .slot-pillar { white-space: nowrap; }

/* Info button for slot description -- replaces the old inline <br><small>. */
.slot-info {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-secondary);
    cursor: help;
    vertical-align: middle;
}
.slot-info:hover { color: var(--color-link); }

/* Break / lunch rhythm rows. Pico's row striping uses --color-bg-subtle
   (neutral-50), so we jump one step darker (neutral-200) to stay visibly
   distinct on BOTH even and odd rows. The !important wins against Pico's
   :nth-child stripe selector. */
.agenda-slots .slot-row.slot-type-break > td,
.agenda-slots .slot-row.slot-type-lunch > td,
.agenda-slots .slot-row.slot-type-networking > td {
    background: var(--color-neutral-200) !important;
    color: var(--color-text-secondary);
    font-style: italic;
}

/* --- Speaker chips ------------------------------------------------------ */

/* Inline chip layout: speakers wrap horizontally to keep the cell short.
   The remove ✗ stays hidden until the chip is hovered/focused so the chip
   reads as a name first. */
.speaker-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.35rem;
}
.speaker-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    padding: 0.2rem 0.6rem;
    background: var(--color-bg-muted);
    border-radius: 999px;
    font-size: 0.75rem;
    line-height: 1.4;
    white-space: nowrap;
}
.speaker-chip-name {
    color: var(--color-text);
    text-decoration: none;
}
.speaker-chip-name:hover { text-decoration: underline; color: var(--color-link); }
.speaker-chip-remove {
    margin: 0;
    display: inline-flex;
    opacity: 0;
    transition: opacity 0.1s ease;
}
.speaker-chip:hover .speaker-chip-remove,
.speaker-chip:focus-within .speaker-chip-remove { opacity: 1; }
.speaker-chip-remove .btn-icon-danger {
    padding: 0;
    width: 0.75rem;
    height: 0.75rem;
    min-height: 0;        /* defeat the global button { min-height: 44px } that
                             otherwise inflates the chip's inline-flex cross-axis */
    min-width: 0;
    line-height: 1;
}

/* + trigger: just the icon at rest. Clicking opens a popover with the
   two dropdowns and a confirm button. */
.speaker-add { position: relative; display: inline-flex; }
.speaker-add > summary.speaker-add-trigger {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.15rem;
    border-radius: 4px;
}
.speaker-add > summary.speaker-add-trigger::-webkit-details-marker { display: none; }
.speaker-add > summary.speaker-add-trigger::marker { display: none; }
.speaker-add > summary.speaker-add-trigger:hover { background: var(--color-bg-muted); }
.speaker-add[open] > summary.speaker-add-trigger { background: var(--color-bg-muted); }
.speaker-add-form {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 60;
    display: flex;
    gap: 0.25rem;
    padding: 0.4rem;
    margin-top: 0.25rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    box-shadow: var(--shadow-md, 0 4px 8px rgba(0, 0, 0, 0.08));
    white-space: nowrap;
}
.speaker-add-form select.table-action-select {
    width: auto;
    min-width: 9rem;
    max-width: 13rem;
    margin: 0;
}

/* --- Person picker popover (existing) ----------------------------------- */

/* Inline assign-speaker form lives in the same flex column as the speaker
   list. Selects stay narrow so they don't blow out the agenda column. */
/* Person picker popover. Replaces the native <datalist> so the dropdown
   respects substring matches the server returns (datalist would prefix-only). */
.person-picker { position: relative; }
.picker-results {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 50;
    margin: 0.125rem 0 0;
    padding: 0;
    list-style: none;
    max-height: 16rem;
    overflow-y: auto;
    background: var(--card-background-color, #fff);
    border: 1px solid var(--color-border, #d1d5db);
    border-radius: 4px;
    box-shadow: var(--shadow-md, 0 4px 8px rgba(0, 0, 0, 0.08));
}
.picker-results li {
    display: flex;
    flex-direction: column;
    padding: 0.4rem 0.6rem;
    cursor: pointer;
    border-bottom: 1px solid var(--color-bg-subtle);
}
.picker-results li:last-child { border-bottom: none; }
.picker-results li:hover,
.picker-results li.is-active { background: var(--color-bg-muted); }
.picker-results__main { font-size: 0.9rem; }
.picker-results__sub {
    font-size: 0.75rem;
    color: var(--color-text-muted, #6b7280);
}

.speaker-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
}
.speaker-row .table-action-form { margin: 0; }

.speaker-row--add { margin-top: 0.25rem; }
.speaker-row--add select.table-action-select {
    width: auto;
    min-width: 0;
    max-width: 11rem;
    margin: 0;
}

/* ============================================================
   UTM target URL: dropdown + read-only URL preview side by side
   ============================================================ */
.utm-target-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
    align-items: end;
    margin-bottom: var(--space-4);
}

.utm-custom-url-row {
    margin-bottom: var(--space-4);
}

.url-preview-label {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-secondary);
    margin-bottom: var(--space-1);
}

.utm-url-preview {
    font-size: var(--font-size-sm);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--pico-border-radius, var(--radius-md));
    background: var(--color-bg-subtle);
    color: var(--color-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-height: var(--target-size-min, 2.75rem);
    display: flex;
    align-items: center;
}

.utm-url-preview.not-configured {
    color: var(--color-warning-600);
    font-style: italic;
}

.utm-url-preview input[type="url"] {
    border: none;
    background: transparent;
    padding: 0;
    margin: 0;
    width: 100%;
    font-size: var(--font-size-sm);
    color: var(--color-text);
    outline: none;
}

/* ============================================================================

/* ============================================================================
   Attendee feedback (mock-up)
   Used by /conferences/{id}/feedback{,/list,/{rid}}. KPI tiles, rating bars,
   histograms, follow-up list, testimonial list.
   ============================================================================ */

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--space-3);
    margin-top: var(--space-2);
}
.kpi-tile {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md, 6px);
}
.kpi-label {
    font-size: 0.8rem;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.kpi-value {
    font-size: 1.75rem;
    font-weight: 600;
    color: var(--color-text);
    line-height: 1.1;
}

/* ---- Rating bar (inline) ---- */
.rating-bar {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 5rem;
}
.rating-bar-fill {
    display: inline-block;
    height: 6px;
    width: var(--rating-pct, 0%);
    border-radius: 999px;
    transition: width 200ms ease-out;
}
.rating-bar > .rating-bar-fill { /* placeholder: real fill below */
    display: none;
}
.rating-bar::before {
    /* track */
    content: "";
    display: inline-block;
    position: relative;
    height: 6px;
    width: 4rem;
    border-radius: 999px;
    background: var(--color-neutral-100);
    flex-shrink: 0;
    background-image: linear-gradient(to right,
        var(--rating-bar-color, var(--color-neutral-400)) var(--rating-pct, 0%),
        var(--color-neutral-100) var(--rating-pct, 0%));
}
.rating-bar--neutral  { --rating-bar-color: var(--color-neutral-500); }
.rating-bar--warning  { --rating-bar-color: var(--color-warning-500, #d97706); }
.rating-bar--info     { --rating-bar-color: var(--color-info-500, #2563eb); }
.rating-bar--success  { --rating-bar-color: var(--color-success-500, #16a34a); }
.rating-bar-value {
    font-size: 0.8rem;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}
.rating-bar--empty {
    color: var(--color-text-muted);
}

/* ---- Per-dimension histogram ---- */
.rating-block-list {
    display: grid;
    gap: var(--space-5);
    margin-top: var(--space-2);
}
.rating-block-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: var(--space-2);
}
.rating-block-label {
    font-weight: 600;
}
.rating-block-mean {
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}
.histogram {
    display: grid;
    gap: var(--space-1);
}
.histogram-row {
    display: grid;
    grid-template-columns: 2rem 1fr 2.5rem;
    gap: var(--space-2);
    align-items: center;
}
.histogram-bucket {
    font-size: 0.8rem;
    color: var(--color-text-muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.histogram-bar {
    display: block;
    position: relative;
    height: 14px;
    background: var(--color-bg-muted);
    border-radius: 3px;
    overflow: hidden;
}
.histogram-bar-fill {
    display: block;
    height: 100%;
    width: var(--bar-pct, 0%);
    background: var(--color-primary-400);
    transition: width 200ms ease-out;
}
.histogram-count {
    font-size: 0.85rem;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

/* ---- Follow-up list ---- */
.followup-list {
    list-style: none;
    padding: 0;
    margin: var(--space-2) 0 0;
    display: grid;
    gap: var(--space-2);
}
.followup-item {
    display: grid;
    grid-template-columns: minmax(180px, max-content) 1fr auto;
    gap: var(--space-3);
    align-items: center;
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md, 6px);
}
.followup-meta {
    font-size: 0.9rem;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
}

/* ---- Testimonials list ---- */
.testimonial-list {
    list-style: none;
    padding: 0;
    margin: var(--space-2) 0 0;
    display: grid;
    gap: var(--space-4);
}
.testimonial-item {
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-subtle);
    border-left: 3px solid var(--color-primary-400);
    border-radius: var(--radius-sm, 4px);
}
.testimonial-quote {
    margin: 0 0 var(--space-2);
    font-style: italic;
    color: var(--color-text);
}
.testimonial-meta {
    font-size: 0.85rem;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
    color: var(--color-text-muted);
}
.testimonial-meta a { color: inherit; text-decoration: underline; }

/* ============================================================
   Inline-style replacements (UI audit, 2026-06-01)
   ============================================================ */

/* ---- Conflict flash (Person/Talk dedup tables) -------------
   Used by talks/workspace.html, persons/form.html, attendees/list.html
   when an import surfaces two existing records matching different
   identifiers. Replaces the heavy <table style="margin:0;..."> +
   <p style="margin:0;font-size:0.9em"> pattern.                         */
.conflict-flash { text-align: left; }
.conflict-flash__lead { margin-top: var(--space-2); font-size: var(--font-size-sm); }
.conflict-flash__table { margin-top: var(--space-2); width: 100%; font-size: var(--font-size-sm); }
.conflict-flash__table th[data-col-w="28"] { width: 28%; }
.conflict-flash__table th[data-col-w="36"] { width: 36%; }
.conflict-flash__table th[data-col-w="50"] { width: 50%; }
.conflict-flash__table th[data-col-w="30"] { width: 30%; }
.conflict-flash__table th[data-col-w="12"] { width: 12%; }
.conflict-flash__resolve form { margin-bottom: var(--space-2); }
.conflict-flash__resolve form:last-child { margin-bottom: 0; }
.conflict-flash__resolve button { width: 100%; font-size: var(--font-size-sm); padding: var(--space-1) var(--space-2); }
.conflict-flash__table tr { vertical-align: top; }
.conflict-flash__cell p { margin: 0; }
.conflict-flash__cell p + p { font-size: var(--font-size-sm); }
.conflict-flash__more,
.conflict-flash__list { margin-top: var(--space-2); font-size: var(--font-size-sm); }
.conflict-flash__list { padding-left: var(--space-4); }

/* ---- Text wrap utilities ---------------------------------- */
.text-pre-wrap { white-space: pre-wrap; }
.text-break-all { word-break: break-all; }

/* ---- Card-padded variants (comms/detail.html) ------------- */
.card-padded--toast {
    margin: var(--space-3);
    margin-bottom: 0;
}
.card-padded--toast > p { margin: 0; }

/* ---- Status icon tones (onboarding_panel) ----------------- */
.icon-tone-success { color: var(--color-success); }
.icon-tone-warning { color: var(--color-warning); }
.icon-tone-error { color: var(--color-error-text); }
.icon-tone-muted { color: var(--color-text-tertiary); }

/* ---- Integrations dashboard (integrations/list.html) ------ */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-4);
    margin-bottom: var(--space-6);
}
.kpi-card { text-align: center; }
.kpi-card__value { font-size: var(--font-size-2xl); font-weight: 600; }
.kpi-card__value--error { color: var(--color-error-text); }
.kpi-card__value--warning { color: var(--color-warning-text); }
.integration-row__link { text-decoration: none; }
.integration-counts__created { color: var(--color-success-text); }
.integration-counts__updated { color: var(--color-info-text); }
.integration-counts__warning { color: var(--color-warning-text); }
.integration-counts__error   { color: var(--color-error-text); }
.integration-card { margin-top: var(--space-6); }
.integration-card--error   { border-left: 4px solid var(--color-error); }
.integration-card--warning { border-left: 4px solid var(--color-warning); }
.integration-warnings {
    margin: var(--space-2) 0 0;
    padding-left: var(--space-6);
    max-height: 480px;
    overflow-y: auto;
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.875rem;
    line-height: 1.5;
}
.integration-warnings > li {
    padding: var(--space-1) 0;
    border-bottom: 1px dashed var(--muted-border-color);
    word-break: break-word;
}
.integration-warnings > li:last-child { border-bottom: 0; }


/* ---- Talks workspace (kanban small bits) ------------------ */
.kanban-empty {
    text-align: center;
    padding: var(--space-4) 0;
}
.kanban-sync-form {
    display: inline;
    margin-left: var(--space-1);
}
.cfp-fallback {
    margin-bottom: var(--space-2);
    font-size: var(--font-size-sm);
}
.cfp-fallback input[type="file"] { font-size: var(--font-size-sm); }
.text-center { text-align: center; }
.conflict-flash__table--fixed { table-layout: fixed; margin-top: var(--space-3); }
.mt-0 { margin-top: 0; }
.integration-row { vertical-align: top; }

/* ---- Email subject bar (comms/detail.html, ADR 009) ------- */
.email-subject-bar {
    margin: var(--space-3);
    margin-bottom: 0;
    padding: var(--space-2) var(--space-3);
    background: var(--pico-form-element-background-color, var(--color-bg-subtle));
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--color-info);
}
.w-icon { width: 24px; }

/* ---- Misc utilities ---------------------------------------- */
/* Utility class — must beat any later display:flex/grid/block declaration
   (e.g. `.agrid-segcol { display: flex }`). `!important` is intentional;
   `.hidden` is a global hide override applied dynamically by JS. */
.hidden { display: none !important; }
.text-uppercase { text-transform: uppercase; }
.text-mono { font-family: var(--font-family-mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace); }
.w-narrow-input { width: 8rem; }
.btn-mini { font-size: var(--font-size-sm); padding: var(--space-1) var(--space-2); }

/* ---- Communication calendar legend swatches --------------- */
.channel-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 2px;
    vertical-align: middle;
}
.channel-swatch--linkedin-post { background: #0077B5; }
.channel-swatch--linkedin-dm   { background: #004182; }
.channel-swatch--bluesky       { background: #7B68EE; }
.channel-swatch--press-release { background: #2E8B57; }

/* ---- Style-guide preview pane (llm_config) ---------------- */
.style-guide-pre {
    padding: var(--space-3);
    font-size: var(--font-size-sm);
    white-space: pre-wrap;
    max-height: 400px;
    overflow-y: auto;
}

/* ---- LLM config preview-form row -------------------------- */
.llm-preview-form {
    display: flex;
    gap: var(--space-3);
    align-items: flex-end;
}
.llm-preview-form > label { flex: 0 0 auto; }

/* ---- Speaker card (kanban-style status row) --------------- */
.speaker-card-head {
    display: flex;
    justify-content: space-between;
    align-items: start;
}
.speaker-card-title {
    font-weight: 600;
    text-decoration: none;
}
.speaker-card-badge { font-size: 0.65rem; }
.speaker-card-meta {
    font-size: var(--font-size-sm);
    color: var(--color-text-tertiary);
    margin-top: var(--space-1);
}
.speaker-card-meta--small {
    font-size: var(--font-size-xs, 12px);
    color: var(--color-text-tertiary);
    margin-top: 2px;
}
.speaker-card-status-form { margin: var(--space-1) 0 0 0; }
.speaker-card-status-form select { font-size: var(--font-size-xs, 12px); padding: 2px var(--space-1); margin: 0; }

/* ---- Form info banner (speakers/form) --------------------- */
.form-info { margin-bottom: var(--space-4); }
.form-info p { margin: 0; }

.dt-indent { padding-left: var(--space-5); }
.action-inline { display: inline-block; margin-left: var(--space-2); }

/* ---- Prompt-preview pane (communication/partials) --------- */
.card-code { background: var(--pico-code-background-color, var(--color-bg-subtle)); }
.prompt-pre {
    white-space: pre-wrap;
    font-size: 0.78rem;
    max-height: 200px;
    overflow-y: auto;
}
.prompt-pre--large { max-height: 400px; margin-bottom: 0; }
.prompt-pre + h4 { margin-top: var(--space-3); }
.prompt-pre + .prompt-pre--large { margin-top: var(--space-2); }

/* ---- draft_result mid-card button row --------------------- */
.draft-card-actions { padding: 0 var(--space-3) var(--space-3); }
.details-summary-padded { padding: var(--space-2) var(--space-3); cursor: pointer; }
.details-body-padded { padding: var(--space-2) var(--space-3); }

/* ---- campaigns/detail pre + note blocks ------------------- */
.campaign-template-pre {
    white-space: pre-wrap;
    font-size: var(--font-size-sm);
    padding: var(--space-3);
}

/* ---- comms/form optional-prompt section (dashed) ---------- */
.form-section-optional {
    margin-top: var(--space-4);
    border: 1px dashed var(--pico-muted-border-color, var(--color-border));
    padding: var(--space-3);
}
.form-section-optional > summary {
    cursor: pointer;
    font-weight: 600;
}

/* ---- inline-block spacing for speakers/workspace mini items */
.inline-tile {
    display: inline-block;
    margin: var(--space-1);
}


/* ---- Final straggler utilities ---------------------------- */
.self-end { align-self: end; }
.legend-spread { width: 100%; display: flex; align-items: center; }
.legend-spread__trailing { margin-left: auto; }
.timing-row__label { flex: 2; }
.button-group--center { justify-content: center; }
.text-meta { font-weight: 500; font-size: var(--font-size-sm); }
.booklet-subtitle { margin-top: 1.5cm; font-size: 12pt; }
.icon-aligned-warning { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }

/* --------------------------------------------------------------------------
   Onboarding panel (ADR 009 §12, redesigned 2026-06-01)
   Unified PanelRow rendering — see app/templates/components/onboarding_panel.html
   and the project-onboarding-auto-closure memory. Reuses .icon-tone-* and
   .w-icon from the inline-style audit block above.
-------------------------------------------------------------------------- */
.onboarding-zones {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-5, 1.25rem);
}
@media (max-width: 720px) {
    .onboarding-zones { grid-template-columns: 1fr; }
}
.onboarding-zone__head {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
    margin: 0 0 var(--space-2);
    font-weight: 600;
}
.onboarding-step-table {
    width: 100%;
    border-collapse: collapse;
    margin: 0;
}
.onboarding-step-table tr.step-row td {
    padding: var(--space-1) var(--space-1);
    border: none;
    vertical-align: top;
    font-size: var(--font-size-sm);
}
.onboarding-step-table tr.step-row:hover {
    background: var(--color-bg-subtle);
}
.onboarding-step-table .step-row__action { width: 52px; text-align: right; }
.onboarding-step-table .step-row--done .step-row__label { color: var(--color-text-muted); }

/* Icon-only contextual button inside the dense onboarding tables.
   Kept at WCAG 2.5.5 minimum (44×44) for hit-target compliance, but
   visually quiet: thin border, transparent until hover. The global
   ``button { min-width: 7.5rem }`` floor is explicitly overridden because
   it's meant for labelled CTAs, not icon affordances. */
.step-btn-icon,
button.step-btn-icon,
a.step-btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    margin: 0;
    flex: 0 0 auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text);
    cursor: pointer;
    text-decoration: none;
}
.step-btn-icon:hover {
    background: var(--color-bg-muted, var(--color-bg-subtle));
}

.badge-auto,
.badge-auto-future {
    display: inline-block;
    font-size: var(--font-size-xs, 0.7rem);
    padding: 0.05rem 0.35rem;
    border-radius: var(--radius-sm);
    margin-left: var(--space-1);
    font-weight: 500;
    vertical-align: middle;
    line-height: 1.4;
}
.badge-auto {
    background: var(--color-info-soft, var(--color-info-bg, #dbeafe));
    color: var(--color-info-text, #1e40af);
}
.badge-auto-future {
    background: var(--color-warning-soft, var(--color-warning-bg, #fef3c7));
    color: var(--color-warning-text, #92400e);
}
.text-auto-closed {
    color: var(--color-info-text);
}

.onboarding-done-disclosure { margin-top: var(--space-2); }
.onboarding-done-disclosure > summary {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    cursor: pointer;
    padding: var(--space-1);
    list-style: none;
    display: flex;
    align-items: center;
    gap: var(--space-1);
}
.onboarding-done-disclosure > summary::-webkit-details-marker { display: none; }
.onboarding-done-disclosure[open] > summary { color: var(--color-text); }

/* ============================================================
   PHONE INPUT (shared/_macros.html phone_input)
   Country dial code dropdown + national-number input. Side by side
   when the column is wide enough (>=24rem); stacked when narrow (the
   persons form's form-row-3 layout puts phone in a ~14rem column).
   Heights are normalised so the select doesn't sit shorter than the
   input under default Pico styling.
   ============================================================ */
/* Phone input — two stacked Pico form elements (dial select + national
   tel input) inside a wrapper. The wrapper inherits no Pico styling
   itself; we only need to:
     1. give it the same bottom margin a single <input> would carry so
        the next field doesn't crowd it;
     2. stop the children from collapsing their bottom margin (the
        wrapper handles vertical rhythm now).
   We DON'T force `height` on the children -- Pico's intrinsic
   form-element height already applies, and overriding it with calc
   risks de-syncing from the sibling <select>/<input> the user sees on
   the other half of the row. */
.phone-input {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: stretch;
    margin-bottom: var(--pico-spacing, var(--space-3));
}
.phone-input__dial,
.phone-input__national {
    min-width: 0;
    margin-bottom: 0;
}
.phone-input__dial { flex: 1 1 14ch; }
.phone-input__national { flex: 2 1 12ch; }

/* ============================================================
   Agenda anchored grid (2026-06-11 redesign, mock-up B v2)
   Day tabs + track multiselect, programme-template toolbar,
   per-track segment columns split by anchored breaks, talk tray.
   ============================================================ */
.agrid-filterbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-bottom: var(--space-3);
}
.agrid-daytabs {
    display: flex;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.agrid-daytabs a {
    padding: var(--space-2) var(--space-4);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    text-decoration: none;
    border-right: 1px solid var(--color-border);
    background: var(--color-surface);
}
.agrid-daytabs a:last-child { border-right: none; }
.agrid-daytabs a.active {
    background: var(--color-primary-400);
    color: var(--color-text-on-primary);
    font-weight: 600;
}
.agrid-trackdd { position: relative; }
/* Match the day-tab height/typography so the toolbar reads as one row
   (day-tabs use --space-2/--space-4 padding + --font-size-sm). */
.agrid-trackdd > button {
    margin-bottom: 0;
    height: auto;
    min-height: 0;
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    line-height: 1.3;
}
.agrid-ddpanel {
    position: absolute;
    top: calc(100% + var(--space-1));
    left: 0;
    z-index: 70;
    min-width: 15rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-2);
}
.agrid-ddpanel label {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    font-size: var(--font-size-sm);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    cursor: pointer;
    margin: 0;
}
.agrid-ddpanel label:hover { background: var(--color-bg-muted); }
.agrid-ddpanel input[type="checkbox"] { margin: 0; }
.agrid-dd-done { width: 100%; margin: var(--space-2) 0 0; }

.agrid-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    flex-wrap: wrap;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-4);
    margin-bottom: var(--space-3);
}
.agrid-toolgrp {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}
.agrid-stepper {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    margin: 0;
}
/* Specificity must beat `button { min-height: var(--target-size-min) }`.
   These steppers live in toolbars / row controls where 2rem is the target;
   the WCAG --target-size-min floor is satisfied by the surrounding hit-area
   (toolbar button group + ample horizontal padding).

   Inner button height = 2rem minus the stepper's hairline top+bottom
   border so the FULL widget outer-height equals 2rem — matching the
   anchor-add row's input/Add button outer-height exactly. Without this,
   the widget renders a hairline taller per side and visibly drifts from
   the row below. */
.agrid-stepper button {
    border: none;
    background: none;
    color: var(--color-text-secondary);
    font-weight: 700;
    padding: 0 var(--space-2);
    margin: 0;
    width: auto;
    height: calc(2rem - 2px);                    /* css-tokens: allow */
    min-height: calc(2rem - 2px);                 /* css-tokens: allow */
    line-height: 1;
    box-sizing: border-box;
}
.agrid-stepper .v { line-height: calc(2rem - 2px); }   /* css-tokens: allow */
.agrid-stepper .v {
    min-width: 3.5rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
    font-size: var(--font-size-sm);
}
.agrid-stepper-sm { border-radius: var(--radius-full); }
.agrid-stepper-sm .v { min-width: 3rem; font-size: var(--font-size-xs); }
.agrid-anchor-add {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
}
.agrid-anchor-add input[type="text"] { width: 8rem; }
/* Specificity must beat the global `input:not(...):not(...)` rule and `button { min-height }`.
   Goal: every control in the toolbar at exactly 2rem — compact, aligned. */
.agrid-anchor-add input:not([type="checkbox"]):not([type="radio"]),
.agrid-anchor-add button {
    margin: 0;
    padding: var(--space-1) var(--space-2);
    width: auto;
    height: 2rem;
    min-height: 2rem;
    font-size: var(--font-size-sm);
    line-height: 1.2;
    box-sizing: border-box;
}

.agrid-layout { display: flex; gap: var(--space-4); align-items: flex-start; }
.agrid-main { flex: 1; min-width: 0; }

.agrid-headrow, .agrid-segrow { display: flex; gap: var(--space-3); }
.agrid-headrow {
    /* Stick BELOW the global navbar (.navbar uses var(--navbar-height)).
       Without offset, the navbar covers the headrow on scroll. */
    position: sticky;
    top: var(--navbar-height);
    z-index: 9;                 /* below navbar (100) but above slot rows */
    background: var(--color-bg);
    padding-top: var(--space-2);
    padding-bottom: var(--space-1);
}
.agrid-headcell {
    flex: 1;
    min-width: 17.5rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-top: 3px solid var(--color-primary-400); /* css-tokens: allow */
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
}
.agrid-headline { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.agrid-ends { margin-left: auto; font-variant-numeric: tabular-nums; }
.agrid-headmeta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-top: var(--space-1);
}
.agrid-headmeta .action-group { margin-left: auto; }

.agrid-segcol {
    flex: 1;
    min-width: 17.5rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-top: none;
    padding: var(--space-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.agrid-segmeta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-top: auto;
    padding-top: var(--space-1);
}
.agrid-segmeta select {
    font-size: var(--font-size-xs);
    width: auto;
    margin: 0;
    padding: var(--space-1) var(--space-6) var(--space-1) var(--space-2);
    background-color: var(--color-bg-subtle);
    color: var(--color-text-secondary);
}
.agrid-addrow { margin: 0; }
.agrid-overflow {
    background: var(--color-error-600);
    color: var(--color-neutral-50);
    border-radius: var(--radius-full);
    padding: 0 var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: 700;
}

.agrid-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    border: 1px solid var(--color-border-strong);
    border-left: var(--space-1) solid var(--color-info-500);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
    /* Tight vertical padding — the row's visual height is driven by the
       tallest control (2rem stepper). Lower padding = more rows visible. */
    padding: 2px var(--space-2);                 /* css-tokens: allow */
    min-height: 2.25rem;
    font-size: var(--font-size-xs);
}
/* Scoped overrides for controls living inside a slot row — must override
   the global `button { min-height: var(--target-size-min) }` floor without
   affecting other stepper/btn-icon instances on the page. */
.agrid-row .agrid-stepper-sm button {
    height: 1.5rem;
    min-height: 1.5rem;
    padding: 0 var(--space-1);
    font-size: var(--font-size-xs);
    line-height: 1;
}
.agrid-row .agrid-stepper-sm .v {
    min-width: 2.75rem;
    font-size: 11px;                              /* css-tokens: allow */
}
.agrid-row .btn-icon,
.agrid-row .btn-icon-danger {
    height: 1.5rem;
    min-height: 1.5rem;
    padding: 0 var(--space-1);
}
.agrid-row.k-keynote, .agrid-row.k-opening_remarks, .agrid-row.k-closing_remarks {
    border-left-color: var(--color-primary-400);
    background: var(--color-primary-50);
}
.agrid-row.k-panel, .agrid-row.k-roundtable { border-left-color: var(--color-warning-500); }
.agrid-row.k-workshop, .agrid-row.k-mentoring, .agrid-row.k-think_tank { border-left-color: var(--color-success-500); }
.agrid-row.k-break {
    border-left-color: var(--color-neutral-300);
    background: var(--color-bg-muted);
}
.agrid-row.dragging { opacity: 0.4; }
.agrid-row.dragover { outline: 2px dashed var(--color-primary-400); outline-offset: 1px; }
.agrid-row[draggable="true"] { cursor: grab; }
/* Gut renders the time + slot-type chip INLINE on a single line so the row
   stays at one row-height. The chip background separates it visually from
   the time without taking a second line. */
.agrid-gut {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex: none;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-secondary);
}
.agrid-gut .k {
    display: inline-block;
    background: var(--color-bg-subtle);
    color: var(--color-text-tertiary);
    border-radius: var(--radius-sm);
    padding: 1px var(--space-2);                  /* css-tokens: allow */
    font-size: 10px;                              /* css-tokens: allow */
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.4;
}
.agrid-bd {
    flex: 1;
    min-width: 0;
    display: flex;
    /* Centre-align so the pick pill, title and badges all sit on the row's
       vertical centre line alongside the stepper and icon buttons (1.5rem). */
    align-items: center;
    gap: var(--space-2);
    /* No wrap — content stays on one line, title gets truncated if needed. */
    flex-wrap: nowrap;
    overflow: hidden;
}
.agrid-ti {
    font-weight: 600;
    font-size: var(--font-size-sm);
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 0 1 auto;
}
.agrid-spk {
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
}
.agrid-spk a { color: inherit; text-decoration: none; }
.agrid-spk a:hover { text-decoration: underline; color: var(--color-link); }
.agrid-rowactions { display: flex; flex-direction: row; gap: var(--space-1); align-items: center; flex: none; }
.agrid-rowactions form { margin: 0; }

/* Break rename — pencil shown by default, check on focus */
.agrid-break-rename {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    margin: 0;
    flex: 1;
    min-width: 0;
}
/* Specificity must beat the global `input:not(...):not(...)` rule (line ~65),
   which has 0,2,1 and sets `padding: var(--space-2) var(--space-3)` (so the
   input matches the global form-control height). Without the boost, break
   rows render much taller than the standard slot row height. */
.agrid-break-rename input:not([type="checkbox"]):not([type="radio"]) {
    font-weight: 600;
    font-size: var(--font-size-sm);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    padding: 0 var(--space-1);
    margin: 0;
    height: 1.5rem;
    line-height: 1;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
}
.agrid-break-rename input:hover,
.agrid-break-rename input:focus {
    border-color: var(--color-border-strong);
    background: var(--color-surface);
}
.agrid-rename-save { display: none; }
.agrid-rename-edit { display: inline-flex; }
.agrid-break-rename:focus-within .agrid-rename-save { display: inline-flex; }
.agrid-break-rename:focus-within .agrid-rename-edit { display: none; }
/* External pencil lives in .agrid-rowactions for parity with non-break rows;
   hide it while the rename input is focused so the inline check takes over. */
.agrid-row:has(.agrid-break-rename:focus-within) .agrid-break-edit { display: none; }
/* Same toggle for anchor-bar rename */
.agrid-anchor-rename .agrid-rename-save { display: none; }
.agrid-anchor-rename .agrid-rename-edit { display: inline-flex; }
.agrid-anchor-rename:focus-within .agrid-rename-save { display: inline-flex; }
.agrid-anchor-rename:focus-within .agrid-rename-edit { display: none; }

.agrid-pick { display: inline-flex; flex-direction: column; align-items: stretch; min-width: 0; max-width: 100%; }
/* The pick is now a plain <button> (was <summary>) so its box geometry is
   identical to the stepper buttons — no native list-item / details quirks
   to fight. Same hairline-border-each-side total height as the stepper
   outer so the pill sits exactly on the row's vertical centre line. */
.agrid-pick-btn {
    border: 1px dashed var(--color-neutral-300);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text-tertiary);
    font-size: var(--font-size-xs);
    font-weight: 400;
    line-height: 1;
    box-sizing: border-box;
    height: calc(1.5rem + 2px);                   /* css-tokens: allow */
    min-height: 0;
    padding: 0 var(--space-2);
    margin: 0;
    width: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
}
.agrid-pick-btn:hover { border-color: var(--color-border-strong); color: var(--color-text-secondary); }
.agrid-pickform { display: flex; gap: var(--space-2); margin: var(--space-1) 0 0; }
.agrid-pickform select { font-size: var(--font-size-xs); margin: 0; width: auto; flex: 1; }
.agrid-pickform button { margin: 0; padding: var(--space-1) var(--space-2); width: auto; }

/* Type-change popover. The pen icon uses the SAME markup as the
   send-back-to-tray button (form > button.btn-icon) so the two render at
   identical position and size; only the popover panel is extra. The
   panel is absolutely positioned so opening it does not change row
   heights or shift adjacent rows. */
.agrid-typepick { position: relative; display: inline-flex; }
.agrid-typepick > form { display: inline-flex; align-items: center; }
.agrid-typeform {
    position: absolute;
    top: calc(100% + var(--space-1));
    right: 0;
    z-index: 70;
    display: inline-flex;
    gap: var(--space-2);
    align-items: center;
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-2);
}
.agrid-typeform select {
    margin: 0;
    width: auto;
    font-size: var(--font-size-xs);
    min-width: 10rem;
}
.agrid-typeform > button {
    margin: 0;
    width: auto;
    padding: var(--space-1) var(--space-2);
    min-height: 1.75rem;
}

.agrid-anchorbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin: var(--space-2) 0;
    background: var(--color-bg-inverted);
    color: var(--color-text-inverted);
    border-radius: var(--radius-md);
    padding: var(--space-1) var(--space-3);
    font-size: var(--font-size-sm);
}
.agrid-anchorbar .tm { font-variant-numeric: tabular-nums; opacity: 0.85; }
.agrid-anchorbar .all { margin-left: auto; opacity: 0.7; }
.agrid-anchor-rename { display: inline-flex; align-items: center; gap: var(--space-1); margin: 0; flex: 1; min-width: 0; }
.agrid-anchor-rename input {
    font-weight: 700;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text-inverted);
    padding: 0 var(--space-2);
    margin: 0;
    height: auto;
}
.agrid-anchor-rename input:hover, .agrid-anchor-rename input:focus {
    border-color: var(--color-neutral-500);
    background: var(--color-neutral-700);
}
.agrid-anchor-rename .btn-icon { color: var(--color-neutral-300); }
.agrid-stepper-dark { border-color: var(--color-neutral-600); background: transparent; }
.agrid-stepper-dark button, .agrid-stepper-dark .v { color: var(--color-text-inverted); }
.agrid-stepper-dark .v { font-size: var(--font-size-xs); min-width: 3rem; }
.agrid-anchor-del {
    border: none;
    background: none;
    color: var(--color-neutral-400);
    padding: 0 var(--space-1);
    margin: 0;
    width: auto;
}
.agrid-anchor-del:hover { color: var(--color-error-400); }

.agrid-tray {
    width: 18.75rem;
    flex: none;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    position: sticky;
    top: var(--space-3);
    max-height: calc(100vh - var(--space-8));
    display: flex;
    flex-direction: column;
}
.agrid-tray h2 {
    font-size: var(--font-size-sm);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-tertiary);
    margin: 0 0 var(--space-2);
}
.agrid-tray-search { position: relative; }
.agrid-search-icon {
    position: absolute;
    left: var(--space-3);
    /* The lucide SVG glyph occupies ~70% of its 14×14 bounding box; the
       remaining whitespace is at the bottom. Anchoring at top:50%/-50%
       (geometric centre of the box) puts the glyph visually low. Anchor
       slightly above to compensate. */
    top: calc(50% - 1px);                         /* css-tokens: allow */
    transform: translateY(-50%);
    color: var(--color-text-tertiary);
    pointer-events: none;
}
/* Specificity must beat the global `input:not(...):not(...)` rule (line ~65), which
   uses :not() to hit 0,2,1 and sets `padding` shorthand (resetting padding-left).
   Generous left padding gives breathing room between the icon and the placeholder
   text, accounting for the lucide SVG's transparent margin. */
.agrid-tray-search input:not([type="checkbox"]):not([type="radio"]) {
    margin-bottom: var(--space-2);
    padding: var(--space-2) var(--space-3) var(--space-2) calc(var(--space-3) + 14px + var(--space-3));   /* css-tokens: allow */
    /* Pico ships a faded magnifier SVG as the input's background-image and
       reserves left padding for it; our custom lucide icon overlays it,
       producing TWO visible magnifiers. Suppress Pico's. Same pattern as
       `.list-search input[type="search"]` above. */
    background-image: none !important;
}
/* Suppress the Webkit/Chromium native search decoration and clear-button so
   the custom lucide icon is the only visible adornment. */
.agrid-tray-search input[type="search"]::-webkit-search-decoration,
.agrid-tray-search input[type="search"]::-webkit-search-cancel-button,
.agrid-tray-search input[type="search"]::-webkit-search-results-button,
.agrid-tray-search input[type="search"]::-webkit-search-results-decoration {
    display: none;
    -webkit-appearance: none;
}
.agrid-tray-list { overflow-y: auto; flex: 1; }
.agrid-tray-card {
    border: 1px solid var(--color-border);
    border-left: var(--space-1) solid var(--color-primary-400);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    padding: var(--space-2) var(--space-3);
    margin-bottom: var(--space-2);
    font-size: var(--font-size-sm);
    cursor: grab;
    box-shadow: var(--shadow-sm);
}
.agrid-tray-card.dragging { opacity: 0.4; }
.agrid-tray-card .t { font-weight: 600; line-height: 1.3; }
.agrid-tray-card .m {
    color: var(--color-text-tertiary);
    font-size: var(--font-size-xs);
    margin-top: 2px; /* css-tokens: allow */
    display: flex;
    gap: var(--space-2);
    align-items: center;
    flex-wrap: wrap;
}
