/*
 * UPTimePress base layer: layout and behavior (grid, fixed card sizing, image cropping, line
 * clamps, overlay/modal positioning, scroll lock, focus state), plus every design token's
 * default. The cosmetic layer (colors, type, spacing, radii, shadows) is uptimepress-theme.css.
 * A theme can drop that layer (`uptimepress_enqueue_theme_css` filter) and keep this one, or drop
 * both (`uptimepress_enqueue_css`). See readme.txt, "Theming".
 *
 * Specificity: rules that must beat Salient are scoped `.uptimepress-panel .uptimepress-card ...`
 * (three classes, against Salient's `.row .col h4`/`.row .col img` at two classes and an element)
 * instead of using !important. Everything else is a single class. Tokens are set under :where(),
 * so any selector a theme writes wins over these defaults regardless of load order.
 */

/* ---- Design tokens ------------------------------------------------------------------------
 * Set any of these on `.uptimepress-panel, .uptimepress-overlay, .uptimepress-event` (or a narrower
 * selector, e.g. one panel's wrapper) to restyle without touching selectors. The overlay is
 * appended to <body>, so tokens set only on a panel don't reach it. `.uptimepress-event` is the
 * plugin's fallback show and class page. */
:where(.uptimepress-panel, .uptimepress-overlay, .uptimepress-event) {
    /* Type. --uptimepress-font applies to card and modal text; titles keep the theme's own
     * heading font (Salient sets one on h2/h4). */
    --uptimepress-font: inherit;
    --uptimepress-title-size: 13px;
    --uptimepress-title-weight: 700;
    --uptimepress-title-line-height: 1.25;
    --uptimepress-meta-size: 12px;
    --uptimepress-meta-line-height: 1.3;
    --uptimepress-summary-size: 12px;
    --uptimepress-summary-line-height: 1.4;
    --uptimepress-small-size: 11px;
    --uptimepress-badge-size: 12px;
    --uptimepress-daybadge-size: 11px;
    --uptimepress-notice-size: 13px;

    /* Color */
    --uptimepress-card-bg: #fff;
    --uptimepress-text: #1a1a1a;
    --uptimepress-meta-opacity: 0.8;
    --uptimepress-muted-opacity: 0.5;
    --uptimepress-image-bg: rgba(0, 0, 0, 0.04);
    --uptimepress-accent: #dc2626;
    --uptimepress-accent-hover: #b91c1c;
    --uptimepress-accent-text: #fff;
    --uptimepress-waitlist-bg: rgba(220, 38, 38, 0.5);
    --uptimepress-closed-bg: #e5e5e5;
    --uptimepress-closed-text: #555;
    --uptimepress-badge-bg: rgba(0, 0, 0, 0.72);
    --uptimepress-badge-text: #fff;
    --uptimepress-error-text: #b32d2e;
    --uptimepress-error-bg: #fbeaea;

    /* Day-of-week badge, mirroring WebsitePublishingPane.jsx's DAY_COLORS. */
    --uptimepress-day-sun: #6366f1;
    --uptimepress-day-mon: #0d9488;
    --uptimepress-day-tue: #d97706;
    --uptimepress-day-wed: #e11d48;
    --uptimepress-day-thu: #7c3aed;
    --uptimepress-day-fri: #ea580c;
    --uptimepress-day-sat: #059669;

    /* Shape and spacing */
    --uptimepress-radius: 3px;
    --uptimepress-button-radius: 4px;
    --uptimepress-button-size: 11px;
    --uptimepress-button-weight: 700;
    --uptimepress-button-padding: 5px 12px;
    --uptimepress-gap: 20px;
    --uptimepress-row-gap: 24px;
    --uptimepress-panel-spacing: 2em;
    --uptimepress-card-padding: 14px 10px;
    --uptimepress-card-height: 190px;
    --uptimepress-image-ratio: 5 / 2;
    --uptimepress-card-hover-lift: -2px;
    --uptimepress-card-hover-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);

    /* Modal */
    --uptimepress-overlay-bg: rgba(0, 0, 0, 0.75);
    --uptimepress-modal-bg: #fff;
    --uptimepress-modal-radius: 8px;
    --uptimepress-modal-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
    --uptimepress-modal-max-width: 900px;
    --uptimepress-modal-title-size: 28px;
    --uptimepress-modal-title-size-mobile: 22px;
    --uptimepress-modal-meta-size: 15px;
    --uptimepress-modal-text-size: 16px;
    --uptimepress-modal-cta-size: 18px;
    --uptimepress-modal-cta-padding: 14px 32px;
    --uptimepress-modal-cta-radius: 6px;
    --uptimepress-modal-close-bg: rgba(0, 0, 0, 0.6);
    --uptimepress-modal-close-bg-hover: rgba(0, 0, 0, 0.8);
}

/* ---- Grid: Salient mode (the default `row n-columns` classes) -------------------------------
 * gap: our own flex-wrap (not Salient's own float-based row/col gutter, which this overrides for
 * the purposes of vertical spacing) — without it, wrapped rows on narrow/mobile viewports (where
 * span_X collapses to one card per row) render with zero space between cards. */
.uptimepress-grid.row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--uptimepress-row-gap) var(--uptimepress-gap);
}

/* Salient's own float-grid clearfix (`.row::before,::after { content:" "; display:table; }`)
 * targets any element with the `.row` class, which this element also carries. On a float-based
 * layout that pseudo-element is invisible/harmless, but once we force display:flex above, it
 * becomes a real (zero-width) flex item — and since it only ever exists once, at the very start
 * of the child list, it silently consumes one column-gap's worth of space before the actual
 * first card, on the first row only (confirmed: every other row renders correctly, and the
 * offset exactly matches the gap value). Flex containers never needed float-clearfix in the
 * first place, so simply switching it off here is correct, not a workaround. */
.uptimepress-grid.row::before,
.uptimepress-grid.row::after {
    display: none;
}

/* Salient's grid only applies real span_X percentage widths at 691px and up — below that,
 * .col falls back to its own unconditional width:100% base rule, so every panel (regardless of
 * its configured `columns` attribute) would otherwise render as one full-width, edge-to-edge
 * column on any phone. Force 2 columns instead, matching the website preview's own tile grid,
 * which never drops below 2 either. 690px (not 691px) so there's no overlap with Salient's own
 * breakpoint. */
@media (max-width: 690px) {
    .uptimepress-grid.row > .col {
        /* 50% minus half the column-gap, not a plain 50% — otherwise two full 50%-wide items
         * plus the gap between them exceed the container's width, and flex-wrap (which breaks
         * lines based on each item's own declared size, not post-shrink) puts each item on its
         * own line instead of shrinking them to fit two per line. */
        width: calc(50% - var(--uptimepress-gap) / 2);
    }
}

/* ---- Grid: plugin mode ----------------------------------------------------------------------
 * When a theme's `uptimepress_grid_classes` filter drops Salient's `row`, the grid becomes a plain
 * CSS grid of --uptimepress-columns (set inline by grid.php) columns, two on phones. Zero
 * specificity, so the theme's own `.uptimepress-grid` rules win outright. */
:where(.uptimepress-grid:not(.row)) {
    display: grid;
    grid-template-columns: repeat(var(--uptimepress-columns, 4), minmax(0, 1fr));
    gap: var(--uptimepress-row-gap) var(--uptimepress-gap);
}

@media (max-width: 690px) {
    :where(.uptimepress-grid:not(.row):not(.uptimepress-grid--cols-1)) {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---- Card ----------------------------------------------------------------------------------- */

/* Image is cropped to --uptimepress-image-ratio (5:2 landscape), regardless of the source image's
 * actual aspect ratio — the CDN helpers only support a width transform, not a height, so
 * cropping happens here instead (docs/Wordpress-plugin-plan.md Part C1). Width-relative, so it
 * scales with column width; only the body below has a fixed height. */
.uptimepress-card-image {
    box-sizing: border-box;
    position: relative;
    overflow: hidden;
    aspect-ratio: var(--uptimepress-image-ratio);
}

/* Three classes and an element: Salient's `.row .col img { height: auto; max-width: 100%;
 * margin-bottom: 15px; }` is two classes and an element, and `height: auto` there would let the
 * image fall back to its native aspect ratio instead of being cropped to the box above (cards
 * of wildly different heights), while its margin opens a gap above the card body. Salient's
 * inline `.row .col img:not([srcset]) { width: auto }` ties this, which is why card images
 * always carry srcset (UPTimePress_Template::image_attrs()). */
.uptimepress-panel .uptimepress-card .uptimepress-card-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    margin: 0;
}

.uptimepress-badge,
.uptimepress-daybadge {
    position: absolute;
    top: 10px;
    left: 10px;
}

/* Day-of-week badge: two stacked lines (day abbreviation + M/D date). */
.uptimepress-daybadge {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* Fixed pixel height, deliberately NOT width-relative (was `aspect-ratio: 5/3`, which made the
 * card a perfect square together with the image above). On the mobile 2-column layout that tied
 * the text body's absolute pixel budget to a ~162px-wide card, leaving ~37px for title+date+
 * summary combined. A fixed height decouples the text budget from column width entirely, while
 * `max-height` at the same value (belt-and-braces alongside `overflow:hidden`) keeps every card
 * in a layout exactly the same height regardless of content length or column width. 190px is
 * sized for the show card's worst case — 2-line title + 1-line date + 3-line summary — plus the
 * CTA row; see docs/Wordpress-plugin-plan.md for the math. Class cards' heavier field list
 * relies on .uptimepress-card-content's fade-mask below rather than fitting within this budget.
 * .uptimepress-card-content is the part that gets clipped when a card has more text than fits;
 * .uptimepress-card-cta never shrinks, so the button always shows. */
.uptimepress-card-body {
    box-sizing: border-box;
    height: var(--uptimepress-card-height);
    max-height: var(--uptimepress-card-height);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.uptimepress-card-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    /* Class cards in particular (schedule/date/venue/teacher/prereq) can still add up to more
     * lines than the fixed box has room for even with title/summary line-clamped — fade instead
     * of a hard clip so an overflowing line trails off rather than slicing mid-character. */
    -webkit-mask-image: linear-gradient(to bottom, #000 80%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 80%, transparent 100%);
}

.uptimepress-card-cta {
    flex: 0 0 auto;
}

/* Line clamps. Title 2 lines; summary 3 (show cards have room a class card's longer field list
 * doesn't); prerequisites 2. */
.uptimepress-panel .uptimepress-card .uptimepress-card-title,
.uptimepress-panel .uptimepress-card .uptimepress-card-summary,
.uptimepress-panel .uptimepress-card .uptimepress-card-prereq {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.uptimepress-panel .uptimepress-card .uptimepress-card-title,
.uptimepress-panel .uptimepress-card .uptimepress-card-prereq {
    -webkit-line-clamp: 2;
}

.uptimepress-panel .uptimepress-card .uptimepress-card-summary {
    -webkit-line-clamp: 3;
}

.uptimepress-panel .uptimepress-card .uptimepress-ticket-button {
    display: inline-block;
}

.uptimepress-waitlist,
.uptimepress-closed {
    cursor: default;
    pointer-events: none;
}

/* The whole card opens the detail overlay (uptimepress-frontend.js). Focus gets the same lift
 * and shadow as hover (uptimepress-theme.css), in place of the browser's outline. */
.uptimepress-card[data-uptimepress-card] {
    cursor: pointer;
}

.uptimepress-card[data-uptimepress-card]:focus-visible {
    transform: translateY(var(--uptimepress-card-hover-lift));
    box-shadow: var(--uptimepress-card-hover-shadow);
    outline: none;
}

/* ---- Overlay and modal ----------------------------------------------------------------------
 * Built once by uptimepress-frontend.js and appended to <body>, so it sits outside any
 * card/grid stacking context and Salient theme chrome. `[hidden]` (the native attribute, toggled
 * by JS) controls visibility rather than a class, to avoid specificity fights with the theme.
 * z-index is deliberately very high for the same reason. */
.uptimepress-overlay {
    position: fixed;
    inset: 0;
    z-index: 999999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.uptimepress-overlay[hidden] {
    display: none;
}

.uptimepress-modal {
    position: relative;
    box-sizing: border-box;
    width: 92%;
    max-width: var(--uptimepress-modal-max-width);
    max-height: 90vh;
    overflow-y: auto;
}

.uptimepress-modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 1;
    width: 36px;
    height: 36px;
    cursor: pointer;
}

.uptimepress-modal-image {
    width: 100%;
    max-height: 420px;
    object-fit: cover;
    display: block;
}

.uptimepress-modal .uptimepress-modal-cta {
    display: inline-block;
}

/* Body scroll-lock while the overlay is open — toggled on <html> by uptimepress-frontend.js. */
.uptimepress-modal-open {
    overflow: hidden;
}

@media (max-width: 690px) {
    .uptimepress-modal {
        width: 100%;
        height: 100%;
        max-height: 100%;
        max-width: 100%;
    }

    .uptimepress-modal-image {
        max-height: 260px;
    }
}

/* ---- Fallback show and class pages (templates/single-show.php, single-class.php) ---------
 * Only when the theme has no uptimepress/single-*.php of its own. */
.uptimepress-event {
    max-width: 900px;
    margin: 0 auto;
    padding: 32px 16px 64px;
}

.uptimepress-event-image,
.uptimepress-event-headshot {
    display: block;
    max-width: 100%;
    height: auto;
}

.uptimepress-event-dates,
.uptimepress-event-facts {
    list-style: none;
    margin: 16px 0;
    padding: 0;
}

.uptimepress-event-date {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    padding: 6px 0;
}

.uptimepress-event-teacher {
    margin-top: 32px;
}
