/* PyLadiesCon portal brand styling.
   Palette + fonts taken from conference.pyladies.com (pyladies/global-conference
   theme.json + base.css): raspberry #ee264d, navy #152035, Blinker + Orbitron. */

:root {
    --pyl-primary: #ee264d;
    --pyl-primary-dark: #c01f3f;
    --pyl-navy: #152035;

    --bs-primary: #ee264d;
    --bs-primary-rgb: 238, 38, 77;
    --bs-primary-text-emphasis: #c01f3f;
    --bs-dark: #152035;
    --bs-dark-rgb: 21, 32, 53;
    --bs-link-color: #ee264d;
    --bs-link-color-rgb: 238, 38, 77;
    --bs-link-hover-color: #c01f3f;
    --bs-link-hover-color-rgb: 192, 31, 63;
}

body {
    font-family: "Blinker", system-ui, sans-serif;
}

/* Display headings, the brand wordmark, and the active-conference badge use the
   conference's geometric display face. */
.navbar-brand,
.display-1,
.display-2,
.display-3,
.display-4,
.display-5,
.display-6 {
    font-family: "Orbitron", system-ui, sans-serif;
    letter-spacing: 0.01em;
}

.btn-primary {
    --bs-btn-bg: #ee264d;
    --bs-btn-border-color: #ee264d;
    --bs-btn-hover-bg: #d11f42;
    --bs-btn-hover-border-color: #d11f42;
    --bs-btn-active-bg: #c01f3f;
    --bs-btn-active-border-color: #c01f3f;
    --bs-btn-disabled-bg: #ee264d;
    --bs-btn-disabled-border-color: #ee264d;
}

.btn-outline-primary {
    --bs-btn-color: #ee264d;
    --bs-btn-border-color: #ee264d;
    --bs-btn-hover-bg: #ee264d;
    --bs-btn-hover-border-color: #ee264d;
    --bs-btn-active-bg: #ee264d;
    --bs-btn-active-border-color: #ee264d;
}

.text-primary {
    color: #ee264d !important;
}

.bg-primary {
    background-color: #ee264d !important;
}

/* The colorful logo needs a light chip to read on the navy navbar. */
.navbar-logo {
    background: #fff;
    padding: 3px;
}

/* django-bootstrap5 tags required fields with the configured
   `required_css_class` ("required") on the field wrapper. Surface that as a
   visible asterisk on the label so it is clear which fields are mandatory. */
.required > .form-label::after {
    content: " *";
    color: var(--bs-danger);
}

/* Contextual left rail (portal/base_sidebar.html): pinned alongside content on
   desktop, an off-canvas drawer on mobile (handled by Bootstrap offcanvas-md). */
@media (min-width: 768px) {
    .app-sidebar {
        position: sticky;
        top: 1rem;
    }
}

/* Bootstrap compiles the active pill colour to a literal blue, so overriding
   --bs-primary alone never reaches it. Point the rail's active item at the
   brand colour instead. */
.app-sidebar .nav-pills {
    --bs-nav-pills-link-active-bg: var(--bs-primary);
}

/* Flex items default to min-width:auto, so a wide table would stretch the
   content column past its grid share and make pages with wide vs narrow
   content render at different widths. Let the column shrink to its share; wide
   tables scroll inside it (wrap them in .table-responsive). */
.app-content {
    min-width: 0;
}

/* Footer resource group headings (portal/_footer_resources.html). */
.footer-heading {
    letter-spacing: 0.04em;
}

/* Speaker checklists (templates/speakers/_checklist_item.html): items the
   portal ticks by itself are dashed so a speaker knows not to tick them. */
.checklist-item-auto {
    border-left: 3px dashed var(--bs-secondary);
}
.checklist-item-manual {
    border-left: 3px solid var(--bs-primary);
}
.checklist-item-done {
    opacity: 0.75;
}
/* Ticking an item redirects back to #item-<pk>; keep it clear of the top. */
.checklist-row {
    scroll-margin-top: 1rem;
}
/* One box size for every row, whether it is a button, a static status, or
   an automatic item: empty while open, ticked once done. */
.checklist-box {
    flex: 0 0 auto;
    width: 1.5rem;
    height: 1.5rem;
    margin-top: 0.1rem;
    padding: 0;
    border: 2px solid var(--bs-secondary);
    border-radius: 0.3rem;
    background: var(--bs-body-bg);
    color: var(--bs-body-bg);
    font-size: 0.85rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
button.checklist-box:hover,
button.checklist-box:focus-visible {
    border-color: var(--bs-primary);
    color: var(--bs-primary);
}
.checklist-box-static {
    border-style: dashed;
    color: var(--bs-secondary);
}
.checklist-box-done,
button.checklist-box-done:hover {
    border-color: var(--bs-success);
    border-style: solid;
    background: var(--bs-success);
    color: #fff;
}
.checklist-box-blocked {
    border-color: var(--bs-danger);
    border-style: solid;
    color: var(--bs-danger);
}
.checklist-box-skipped {
    border-color: var(--bs-secondary);
    color: var(--bs-secondary);
}
/* Waiting: nothing to click yet, and the row says why. */
.checklist-box-waiting {
    border-style: dotted;
    border-color: var(--bs-secondary);
    color: var(--bs-secondary);
    opacity: 0.75;
}
.checklist-row-waiting .checklist-title-waiting {
    color: var(--bs-secondary) !important;
}
.checklist-title-done {
    text-decoration: line-through !important;
    color: var(--bs-secondary) !important;
}
/* Due dates, right-aligned, louder the closer they are. */
.checklist-due {
    /* Bootstrap badges are 0.75em; a deadline deserves body size. */
    font-size: 0.95rem;
    font-weight: 600;
    padding: 0.4em 0.65em;
    white-space: nowrap;
}
.checklist-due-overdue {
    background: var(--bs-danger);
    color: #fff;
}
.checklist-due-soon {
    background: var(--bs-warning);
    color: var(--bs-dark);
}
.checklist-due-later {
    background: var(--bs-primary-bg-subtle);
    color: var(--bs-primary-text-emphasis);
}
.checklist-due-quiet {
    background: transparent;
    border: 1px solid var(--bs-border-color);
    color: var(--bs-secondary);
    font-weight: 400;
}

/* Flash messages as toasts (templates/portal/_toast_messages.html): shown for
   a few seconds, then fade out without JavaScript. */
.portal-toast {
    animation: portal-toast-fade 7s ease-in forwards;
}
@keyframes portal-toast-fade {
    0%, 80% { opacity: 1; }
    100% { opacity: 0; visibility: hidden; }
}

/* Checklist board cells (templates/speakers/checklist_board.html). */
.checklist-board td.cell-done { background: var(--bs-success-bg-subtle); }
.checklist-board td.cell-todo { background: var(--bs-light); }
.checklist-board td.cell-overdue { background: var(--bs-warning-bg-subtle); }
.checklist-board td.cell-blocked { background: var(--bs-danger-bg-subtle); }
.checklist-board td.cell-skipped { background: var(--bs-secondary-bg-subtle); }
.checklist-board td.cell-none { color: var(--bs-secondary); }
.checklist-board th.board-col {
    min-width: 6rem;
    max-width: 8rem;
    white-space: normal;
    vertical-align: bottom;
    line-height: 1.15;
}

/* Template editor (templates/speakers/template_detail.html): the reorder column. */
.col-order {
    width: 5rem;
}

/* Invitation email preview: the sender's own words, set apart from the template. */
.invitation-preview-note {
    background: #fff3cd;
    border-left: 3px solid #ffc107;
    padding: 0.25rem 0.75rem;
}
.invitation-preview-note > :last-child {
    margin-bottom: 0;
}
/* Task stats legend (templates/speakers/_task_stats_cards.html): the "open"
   swatch matches the empty part of the stacked bar. */
.task-legend-open {
    color: var(--bs-secondary-bg);
}

/* Login page (templates/account/login.html): the "or" between the password
   form and the sign-in code. A rule with the word in the middle on narrow
   screens; a vertical rule between the two columns from md up. */
.login-or {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    color: var(--bs-secondary);
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.login-or::before,
.login-or::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--bs-border-color);
}
@media (min-width: 768px) {
    /* The column stretches to the row (align-items-stretch on the parent),
       so the rule is as tall as the taller of the two forms rather than a
       fixed height that could overhang a short one. */
    .login-or {
        flex-direction: column;
        width: auto;
        height: 100%;
        padding: 0 0.5rem;
    }
    .login-or::before,
    .login-or::after {
        border-top: 0;
        border-left: 1px solid var(--bs-border-color);
        width: 0;
    }
}

/* Accordion headers (the propose form's two sections). Bootstrap tints an
   open header and leaves a collapsed one plain white, which stops it
   reading as a header at all: the closed section looked like a stray line
   of text. A collapsed header keeps a tinted background, a border and its
   chevron, so it still looks like something to open. */
.accordion-button {
    font-weight: 600;
}
.accordion-button.collapsed {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}
.accordion-button.collapsed:hover {
    background-color: var(--bs-secondary-bg);
}
.accordion-button:focus {
    box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.25);
}


/* Upload panel (templates/speakers/_upload_panel.html) and the video
   length bar on the performer's session page: tall enough to read the
   percentage inside. */
.upload-progress {
    height: 1.25rem;
}

/* At-a-glance strip on the session pages (templates/speakers/session_detail.html,
   speaker_session_detail.html): one tile per thing that needs a person,
   each a link to its section. The left edge carries the state. */
.glance-tile {
    color: inherit;
    text-decoration: none;
    border-left: 4px solid var(--bs-border-color);
}
.glance-tile:hover {
    border-color: var(--bs-primary);
    color: inherit;
}
.glance-tile.glance-ok {
    border-left-color: var(--bs-success);
}
.glance-tile.glance-warn {
    border-left-color: var(--bs-warning);
}
.glance-tile.glance-bad {
    border-left-color: var(--bs-danger);
}
.glance-label {
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bs-secondary);
}
.glance-value {
    font-weight: 600;
}
.glance-detail {
    font-size: 0.8rem;
    color: var(--bs-secondary);
}
/* A folded card (Activity): the header is the summary. */
details.card > summary.card-header {
    cursor: pointer;
    list-style: none;
}
details.card > summary.card-header::before {
    content: "\25B8";
    display: inline-block;
    width: 1em;
}
details.card[open] > summary.card-header::before {
    content: "\25BE";
}

/* Preview fold on file rows (templates/speakers/_media_preview.html): the
   file at a readable size, never wider than the row. The width and height
   attributes on the image are hints for layout; the real size is the file's. */
.media-preview-image,
.media-preview-video {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 24rem;
}

/* The files table (templates/speakers/_media_files.html): the "More" row
   under a file carries its forms and preview on a quiet background. While
   it is open, it and the file row above it read as one block: the same
   background on both, an accent down their left edge, and a firmer rule
   under the pair, so the panel is not mistaken for another file. */
.media-table .media-group-more > td {
    border-top: 0;
    padding: 1rem 1.25rem 1.25rem;
}
.media-table .media-group:has(> .media-group-more.show) > tr > td {
    --bs-table-bg: var(--bs-tertiary-bg);
}
.media-table .media-group:has(> .media-group-more.show) > tr > td:first-child {
    border-left: 3px solid var(--bs-primary);
}
.media-table .media-group:has(> .media-group-more.show) > .media-group-more > td {
    border-bottom: 2px solid var(--bs-secondary-border-subtle);
}

/* The session picker on the export page (templates/speakers/media_export.html):
   a scrollable list with the type headings inside it. */
.session-picker-list {
    max-height: 18rem;
    overflow-y: auto;
}
.session-picker:disabled {
    opacity: 0.5;
}

/* Thumbnails on file rows, the speaker's files and the board
   (templates/speakers/_media_thumb.html). */
.media-thumb {
    object-fit: cover;
    flex: none;
}
.media-thumb-icon {
    display: inline-flex;
    width: 64px;
    height: 36px;
    align-items: center;
    justify-content: center;
    background: var(--bs-tertiary-bg);
    border-radius: 0.25rem;
    flex: none;
}

/* A transcript or another text file shown in its preview fold. */
.media-preview-text {
    height: 20rem;
}

/* The schedule editor's grid (speakers, task 4.2): the hour gutter, the
   all-channels lane, one column per channel, 15-minute rows. Cards carry
   their grid position inline, computed in speakers/schedule.py. */
.schedule-scroll {
    /* Full height on purpose: the page scrolls a long day, not a box
       within it (the rooms still scroll horizontally when they must,
       and Compact or Fit put the whole day on one screen). */
    overflow-x: auto;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
}
.schedule-grid {
    display: grid;
    grid-template-columns: 4.5rem 7rem repeat(var(--schedule-columns, 0), minmax(12rem, 1fr));
    /* Row 1 is the room headers: content-sized whatever the density,
       so Compact and Fit shrink the quarter-hours, never the heading. */
    grid-template-rows: auto;
    grid-auto-rows: var(--schedule-row-height, 1.5rem);
    position: relative;
}
.schedule-head {
    grid-row: 1;
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color);
    font-weight: 600;
    font-size: 0.85rem;
    padding: 0.25rem 0.5rem;
    white-space: nowrap;
}
.schedule-hour {
    font-size: 0.75rem;
    color: var(--bs-secondary-color);
    border-top: 1px solid var(--bs-border-color-translucent);
    padding: 0 0.25rem;
}
.schedule-cell {
    border-left: 1px solid var(--bs-border-color-translucent);
}
.schedule-cell-hour {
    border-top: 1px solid var(--bs-border-color-translucent);
}
.schedule-cell.schedule-drop {
    background: var(--bs-primary-bg-subtle);
}
.schedule-card {
    position: relative;
    z-index: 2;
    margin: 1px;
    padding: 0.1rem 0.4rem;
    overflow: hidden;
    font-size: 0.8rem;
    line-height: 1.25;
    /* Calendar blue, not the brand red: a placed session is an event,
       not an alert (Bootstrap's blue-100/200). */
    background: #cfe2ff;
    border: 1px solid #9ec5fe;
    border-radius: 0.35rem;
    cursor: grab;
}
/* A card is as tall as its slot, so the title may wrap and use that
   height; the card's own overflow clips whatever still does not fit.
   Only the quarter-hour card keeps the single clipped line. */
.schedule-card-title {
    display: block;
    overflow-wrap: anywhere;
}
.schedule-card-tight .schedule-card-title {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.schedule-card-edit,
.schedule-card .text-warning-emphasis[role="img"] {
    padding: 0 0.3rem;
    font-size: 0.7rem;
    line-height: 1.3;
}
/* A quarter-hour card has one row of pixels: title only, on one line,
   with the full text and times in the tooltip. */
.schedule-card-tight {
    padding-top: 0;
    padding-bottom: 0;
}
.schedule-card-tight .schedule-card-meta,
.schedule-card-tight .schedule-card-warnings {
    display: none;
}
.schedule-band {
    /* Lavender, not grey: a band is the program's own furniture (the
       opening, a break), and grey read as disabled (purple-100/200). */
    background: #e2d9f3;
    border-color: #c5b3e6;
}
.schedule-warned {
    border-color: var(--bs-warning-border-subtle, #ffe69c);
}
.schedule-card-title {
    color: inherit;
    text-decoration: none;
}
.schedule-card-title:hover {
    text-decoration: underline;
}
/* The popover hangs off the pencil itself, so it opens where the
   organizer clicked; anchored to the card, a band's popover sat at the
   card's far right edge, off screen once the grid scrolls. */
.schedule-card-menu {
    position: relative;
}
.schedule-card-menu > summary {
    list-style: none;
    padding: 0 0.3rem;
    line-height: 1.2;
}
.schedule-card-popover {
    position: absolute;
    top: calc(100% + 0.25rem);
    right: 0;
    z-index: 5;
    width: 14rem;
}
/* A band's pencil sits at the grid's left edge, where a right-aligned
   popover would poke into space the scroller cannot reach; it opens
   rightward instead. */
.schedule-band .schedule-card-popover {
    right: auto;
    left: 0;
}
.schedule-resize {
    position: absolute;
    inset: auto 0 0 0;
    height: 0.45rem;
    cursor: ns-resize;
}
.schedule-pending {
    cursor: grab;
}
.schedule-pending .schedule-card-popover {
    width: 13rem;
}
/* The unscheduled list grows with the page on purpose: its own
   scrollbar would clip the place flyouts, which cannot escape an
   overflow container. */
/* text-warning-emphasis is a Bootstrap 5.3 utility; this portal runs
   5.2, so the warning colour is set here with the same 5.3 value. */
.schedule-card-warnings,
.schedule-card .text-warning-emphasis {
    color: var(--bs-warning-text-emphasis, #997404);
}
.schedule-card-warnings {
    line-height: 1.2;
}

/* A grid item's minimum size is its content unless told otherwise, so a
   long title would push a card past its column; the meta line clips the
   same way the title does. */
.schedule-card {
    min-width: 0;
}
.schedule-card-body {
    flex: 1 1 auto;
    min-width: 0;
}
.schedule-card-meta {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* The click-to-add panel, floated at the clicked cell. */
.schedule-cell-panel {
    position: fixed;
    z-index: 40;
    width: 17.5rem;
}
.schedule-cell-options {
    max-height: 14rem;
    overflow: auto;
}
.schedule-cell {
    cursor: pointer;
}

/* While a card's popover is open, the card stops clipping (the popover
   would otherwise be cut to the card's height) and rises above its
   neighbours; schedule-editor.js toggles the class with the menu. */
.schedule-card.schedule-card-open {
    overflow: visible;
    z-index: 20;
}
.schedule-pending.schedule-card-open {
    position: relative;
    z-index: 20;
}

/* On a full-width band the title block does not grow, so the pencil and
   the warning sit beside the title in the all-rooms lane instead of
   drifting over the last room's column. */
.schedule-band .schedule-card-body {
    flex: 0 1 auto;
}

/* Draggables never join a text selection: a drag that starts inside a
   selection would carry the whole selection as its ghost, sidebar
   panels included. */
.schedule-card,
.schedule-pending {
    user-select: none;
}

/* Where the drop would land: the dragged session's footprint, dashed,
   in the hovered room (full width over the all-rooms lane). It takes
   no pointer events, or hovering it would cancel the drop. */
.schedule-drop-preview {
    display: none;
    z-index: 3;
    justify-content: flex-end;
    align-items: flex-end;
    margin: 1px;
    pointer-events: none;
    background: rgba(207, 226, 255, 0.55);
    border: 2px dashed #6ea8fe;
    border-radius: 0.35rem;
}
/* The minute count rides the edge being dragged, on its own chip, so
   it never sits over the card's title. */
.schedule-drop-label {
    margin: 0.15rem;
    padding: 0 0.35rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: #fff;
    background: #084298;
    border-radius: 0.25rem;
}
.schedule-drop-label:empty {
    display: none;
}
/* A band spans the whole grid, so a right-hand chip can sit off
   screen; its chip joins the band's own controls at the left edge. */
.schedule-drop-preview.schedule-drop-band {
    justify-content: flex-start;
}

/* The off-screen clone a drag's image is painted from: rendered (so
   Chrome can rasterize it) but far outside the viewport. Snapshotting
   the live list item dragged its neighbours into the picture. */
.schedule-drag-image {
    position: fixed;
    top: -200vh;
    left: 0;
    z-index: -1;
    pointer-events: none;
    background: var(--bs-body-bg, #fff);
}

/* The presenter's own rows on their schedule page. */
.schedule-mine {
    background: #f6faff;
    border-left: 0.25rem solid #6ea8fe;
}

/* A card whose working position differs from what the speakers see:
   dashed until the next Publish schedule. */
.schedule-card-dirty {
    border-style: dashed;
}

.schedule-card-pencilled {
    border-style: dotted;
    opacity: 0.75;
}

/* Compact and Fit densities (design §10.2): one-line cards, the detail
   stays in the tooltip and the pencil. */
.schedule-density-compact .schedule-card {
    padding-top: 0;
    padding-bottom: 0;
    font-size: 0.7rem;
}
.schedule-density-compact .schedule-card-meta,
.schedule-density-compact .schedule-card-warnings {
    display: none;
}
.schedule-density-compact .schedule-card-title {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.schedule-density-compact .schedule-hour {
    font-size: 0.65rem;
}

/* The subscribe popover holds a whole URL. */
.schedule-feed-popover {
    width: 22rem;
    max-width: 90vw;
}

/* Fit shrinks the lettering with the rows: the text follows the
   computed row height, floored where it stops being readable. */
.schedule-density-fit .schedule-card {
    padding: 0 0.2rem;
    font-size: clamp(7px, calc(var(--schedule-row-height, 1.5rem) * 0.72), 0.7rem);
    line-height: 1.15;
    border-radius: 0.2rem;
}
.schedule-density-fit .schedule-hour {
    font-size: clamp(7px, calc(var(--schedule-row-height, 1.5rem) * 0.72), 0.65rem);
}
.schedule-density-fit .schedule-card-edit,
.schedule-density-fit .schedule-card .text-warning-emphasis[role="img"] {
    padding: 0 0.15rem;
    font-size: clamp(7px, calc(var(--schedule-row-height, 1.5rem) * 0.7), 0.7rem);
    line-height: 1.1;
}

/* The wide (spreadsheet) view breaks out of the page container: full
   viewport width, so every room column gets its share of the screen. */
.schedule-wide {
    position: relative;
    left: 50%;
    width: 100vw;
    margin-left: -50vw;
    padding: 0 1.5rem;
}
