@import url('https://fonts.googleapis.com/css2?family=Rock+Salt&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');

:root {
    color-scheme: light dark;

    --primary-colour: hsl(334, 100%, 32%);
    --primary-dark: color-mix(in hsl, var(--primary-colour), black 20%);
    --primary-light: color-mix(in hsl, var(--primary-colour), white 30%);
    --primary-muted: color-mix(in hsl, var(--primary-colour), gray 40%);
    --primary-shadow: color-mix(in hsl, var(--primary-colour), black 80%);

    --white: hsl(0, 0%, 100%);
    --black: hsl(0, 0%, 0%);

    /* The warm off-white used for text sitting directly on a solid brand-magenta-family background
       (the hero wordmark, the homepage hook section's body column) - deliberately not pure --white.
       Named generically since a third such use should confirm the shade still fits, not just assume. */
    --text-on-brand: #F4F0EC;

    --background: var(--white);
    --surface: var(--white);
    --text: var(--black);
    --text-muted: color-mix(in hsl, var(--text), white 10%);
    --border: var(--primary-light);
    --focus-ring: var(--primary-colour);

    --hover-opacity: 0.1;
    --active-opacity: 0.2;
    --active-hover-opacity: 0.3;

    --hairline-width: 72px;
    --hairline-thickness: 2px;
    --hairline-opacity: 0.3;

    /* Matches TopMenu.razor.css's rendered nav height (40px logo + padding); the hero's
       viewport-fill calc needs this as a shared value since it isn't a descendant of <nav>.
       Keep in sync if TopMenu's padding/logo size ever changes. */
    --nav-height: 72px;
    --nav-height-mobile: 68px;

    --fs-body: 1rem;
    --lh-body: 1.6;
    --fs-section-heading: 1.5rem;
    --lh-section-heading: 1.4;
    --fs-page-heading: 2.25rem;
    --lh-page-heading: 1.2;
    --fs-hero: 3.5rem;
    --lh-hero: 1.1;

    --space-section-y: 2rem;
    --space-section-y-mobile: 1.25rem;
    --space-section-x: 1.5rem;
    --space-section-x-mobile: 1rem;

    font-family: "IBM Plex Sans", Arial, Helvetica, sans-serif;
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    color: var(--text);
    background: var(--background);
}

@media (prefers-color-scheme: dark) {
    :root {
        --background: hsl(0, 0%, 7%);
        --surface: hsl(0, 0%, 11%);
        --text: hsl(40, 20%, 95%);
        --text-muted: color-mix(in hsl, var(--text), black 25%);
        --border: color-mix(in hsl, var(--text), black 46%);
        --focus-ring: var(--white);
    }
}

/* Bootstrap's reboot sets its own literal `body { color; background-color; }` (its dark variant is
   opt-in via `[data-bs-theme=dark]`, which this app never sets), and app.css above only styles `:root`
   (the `<html>` element) - so any element that doesn't set its own explicit background (like
   `.admin-page`) silently inherits Bootstrap's un-themed white body regardless of `prefers-color-scheme`,
   while its own text colour still correctly flips via the `--text`/`--text-muted` custom properties. That
   mismatch - near-white dark-mode text on a body that stays white - is what made the admin conference
   summary and session list unreadable in dark mode even though every token they use was already
   theme-correct. `.page-section` masked the same underlying gap on the public site by always setting its
   own background; this rule fixes it at the source instead of requiring every container to re-assert it. */
body {
    background: var(--background);
    color: var(--text);
}

a {
    text-decoration: none;
    color: inherit;
}

.page-section {
    /* Full-bleed: no width cap, no centering. Its background already matches the page (see the
       flush decision above), so the only thing a cap here was doing was narrowing the content
       (e.g. the speaker grid) for no visible reason - prose stays readable regardless, since
       .text-block .text below caps itself at 720px independently of this element's own width. */
    padding: var(--space-section-y) var(--space-section-x);
    width: 100%;
    background: var(--background);
}

/* Sections sit flush against each other - no boxed card, no margin gap. Where two land back to
   back with nothing full-bleed (like HookSection) between them, a hairline (not a full border)
   marks the seam, consistent with the hairline-divider treatment already used under every h2. */
.page-section + .page-section {
    border-top: var(--hairline-thickness) solid color-mix(in hsl, var(--primary-colour), transparent 70%);
}

/* A split section (two-column colour-blocked layout: HookSection, CodeOfConductSection,
   LocationSection) mirrors its column placement when it renders directly after another one of the
   same kind, so consecutive split sections read as an alternating pair. Purely positional - keyed
   on DOM adjacency between elements carrying .split-section, not on which specific section it is -
   so it keeps working if these sections are reordered or another one is added. `order` only moves
   paint position, not DOM order, so reading/tab order (heading before body) is unaffected. */
.split-section + .split-section .split-column--heading {
    order: 2;
}

.split-section + .split-section .split-column--body {
    order: 1;
}

@media (max-width: 768px) {
    .split-section + .split-section .split-column--heading,
    .split-section + .split-section .split-column--body {
        order: initial;
    }
}

.page-section h2 {
    font-size: var(--fs-section-heading);
    line-height: var(--lh-section-heading);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    text-align: center;
    color: var(--text);
    margin-bottom: 0.75rem;
}

.page-section h2::after {
    content: "";
    display: block;
    width: var(--hairline-width);
    height: var(--hairline-thickness);
    background: var(--primary-colour);
    opacity: var(--hairline-opacity);
    margin: 0.5rem auto 1rem;
}

.hairline-divider {
    display: block;
    width: var(--hairline-width);
    height: var(--hairline-thickness);
    background: var(--primary-colour);
    opacity: var(--hairline-opacity);
}

.text-page-heading {
    font-size: var(--fs-page-heading);
    line-height: var(--lh-page-heading);
}

.text-hero {
    font-size: var(--fs-hero);
    line-height: var(--lh-hero);
}

.text-block {
    text-align: center;
}

.page-section .text-block {
    text-align: left;
}

.page-section .text-block .text {
    color: var(--text-muted);
    font-size: 1.06rem;
    line-height: 1.7;
    max-width: 720px;
    margin: 0 auto;
}

.page-section .text-block .text p {
    margin-bottom: 1rem;
}

@media (max-width: 768px) {
    .page-section {
        padding: var(--space-section-y-mobile) var(--space-section-x-mobile);
    }

    .page-section .text-block .text {
        font-size: 1rem;
        line-height: 1.6;
        max-width: 100%;
    }
}

/* Admin-only page padding. Deliberately not .page-section: that class also carries public-site
   heading/divider rules (centred uppercase h2, hairline underline, section-to-section border) that
   don't fit Admin's left-aligned h1 pages. This is just the spacing, reusing the same tokens so the
   rhythm matches Site's without inheriting its heading styling. */
.admin-page {
    padding: var(--space-section-y) var(--space-section-x);
}

@media (max-width: 768px) {
    .admin-page {
        padding: var(--space-section-y-mobile) var(--space-section-x-mobile);
    }
}

/* Organiser tile grid: shared by the per-conference organiser grid (OrganiserGrid.razor) and the
   global organiser directory (Organisers.razor), both rendering <OrganiserTile> per item. Blazor
   CSS isolation only reaches elements a component itself renders, so a shared component's own
   scoped stylesheet can't cover markup rendered by two different pages - these rules live here
   instead, same reasoning as .admin-page above. */
.organiser-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 1.25rem;
    margin-top: 1rem;
}

.organiser-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    border: 1px solid var(--border);
    border-radius: 0;
    background-color: var(--surface);
    box-shadow: none;
    padding: 0;
    font: inherit;
    text-align: inherit;
    cursor: pointer;
    transition: border-color 150ms ease, background-color 150ms ease;
}

.organiser-card:hover,
.organiser-card:focus-visible {
    border-color: var(--primary-colour);
    background-color: color-mix(in hsl, var(--primary-colour), transparent 95%);
}

.organiser-card img,
.organiser-photo-placeholder {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
}

.organiser-card img {
    object-fit: cover;
    filter: saturate(0.4);
    transition: filter 150ms ease;
}

.organiser-card:hover img,
.organiser-card:focus-visible img {
    filter: saturate(1);
}

.organiser-photo-placeholder {
    background-color: var(--border);
}

.organiser-card .organiser-name {
    margin: 0.6rem 0 0.15rem;
    text-align: center;
    font-weight: 700;
    color: var(--text);
}

.organiser-card .organiser-role {
    margin: 0 0 0.6rem;
    text-align: center;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.organiser-card.organiser-add {
    border-style: dashed;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}

.organiser-card.organiser-add:hover,
.organiser-card.organiser-add:focus-visible {
    color: var(--primary-colour);
    border-color: var(--primary-colour);
    background-color: color-mix(in hsl, var(--primary-colour), transparent 95%);
}

.organiser-add-glyph {
    aspect-ratio: 1 / 1;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.5rem;
    line-height: 1;
}

/* Session list grid: shared by the site's session list (SessionsList.razor in Site) and the
   conference edit page's session grid (SessionsGrid.razor in Admin), both rendering session rows
   with the same visual styling. Blazor CSS isolation only reaches elements a component itself
   renders, so these base/layout rules live here instead of in Site's scoped stylesheet, same
   reasoning as the .organiser-grid block above. Cap/expand/target/deep-link mechanics stay in
   Site's SessionsList.razor.css since they're visitor-specific, not shared. */
.sessions-list-container {
    width: 100%;
}

.sessions-main {
    columns: 2;
    column-gap: 2.5rem;
    column-rule: 1px solid var(--border);
}

.sessions-aside {
    columns: 1;
}

.session-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 0;
    text-decoration: none;
    color: inherit;
    gap: 2rem;
    border-bottom: 1px solid var(--border);
    transition: background-color 0.2s ease;
    break-inside: avoid-column;
}

.session-row:last-child {
    border-bottom: none;
}

.session-row:hover,
.session-row:focus-visible {
    background-color: color-mix(in hsl, var(--primary-colour), transparent 96%);
}

.session-row:focus-visible {
    outline: 3px solid var(--primary-colour);
    outline-offset: -3px;
}

@media (prefers-color-scheme: dark) {
    .session-row:hover,
    .session-row:focus-visible {
        background-color: color-mix(in hsl, var(--primary-colour), transparent 92%);
    }
}

.session-row-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

.session-title-block {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-bottom: 0.5rem;
}

.session-title {
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text);
    margin: 0;
    padding: 0;
}

.session-placement {
    font-size: 0.875rem;
    font-family: IBM Plex Mono, monospace;
    color: var(--text-muted);
    margin: 0;
    padding: 0;
}

.session-speakers {
    font-size: 0.95rem;
    color: var(--text-muted);
    margin: 0;
    padding: 0;
}

@media (max-width: 768px) {
    .sessions-main {
        columns: 1;
    }

    .session-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
        padding: 0.75rem 0;
    }

    .session-title {
        font-size: 0.95rem;
    }

    .session-speakers {
        font-size: 0.9rem;
    }
}

.button-container {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}

.button {
    appearance: none;
    -webkit-appearance: none;
    border: 2px solid var(--primary-colour);
    background: var(--surface);
    color: var(--primary-colour);
    padding: 10px 26px;
    border-radius: 10px;
    font-weight: 700;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03);
}

/* Dark theme: magenta is a solid accent block, never text on the dark surface (see ADR 2) */
@media (prefers-color-scheme: dark) {
    .button {
        background: var(--primary-colour);
        color: var(--white);
    }
}

/* Hover/focus/active/selected all use a solid magenta fill with white text (never magenta text on a
   magenta-tinted background - that moves the background's luminance toward the text's own, which drops
   contrast rather than raising it). This is the same white-on-magenta pairing already verified at ~7.92:1. */
.button:hover,
.button:focus {
    background-color: var(--primary-colour);
    color: var(--white);
    border-color: var(--primary-colour);
    outline: none;
}

@media (prefers-color-scheme: dark) {
    .button:hover,
    .button:focus {
        background-color: var(--primary-dark);
        border-color: var(--primary-dark);
    }
}

.button:active {
    background-color: var(--primary-dark);
    color: var(--white);
    border-color: var(--primary-dark);
}

/* Selected tab state (aria-selected="true") */
.button[aria-selected="true"] {
    background-color: var(--primary-colour);
    color: var(--white);
    border-color: var(--primary-colour);
}

.button:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
}

a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0.001ms !important;
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
    }
}
