
@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-Regular-c8978b37.ttf") format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-Italic-b47ea162.ttf") format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-Medium-fafc359f.ttf") format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-MediumItalic-57058366.ttf") format('truetype');
  font-weight: 500;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-SemiBold-f1f8d504.ttf") format('truetype');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-SemiBoldItalic-35113b97.ttf") format('truetype');
  font-weight: 600;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-Bold-696a1365.ttf") format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: asset-url("/assets/lora/Lora-BoldItalic-fdc5c9f9.ttf") format('truetype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
    /* Apple-style grouped surfaces: a quiet grey ground, white cards, near-black ink */
    :root {
        color-scheme: light;
        --background: 0 0% 100%;
        --foreground: 240 3% 12%;         /* #1D1D1F */
        --card: 0 0% 100%;
        --card-foreground: 240 3% 12%;
        --popover: 0 0% 100%;
        --popover-foreground: 240 3% 12%;
        --primary: 240 3% 12%;
        --primary-foreground: 0 0% 100%;
        --secondary: 240 6% 96%;
        --secondary-foreground: 240 3% 12%;
        --muted: 240 6% 96%;              /* quiet fills */
        --muted-foreground: 240 2% 44%;   /* #6E6E73 */
        --accent: 240 6% 96%;
        --accent-foreground: 240 3% 12%;
        --destructive: 356 100% 42%;      /* #D70015 */
        --destructive-foreground: 0 0% 100%;
        --border: 240 6% 90%;             /* hairlines */
        --input: 240 6% 83%;
        --ring: 211 100% 50%;
        --gold: 38 72% 40%;               /* from the Sanjola mark: "next" and the calendar leaf */
        --plan-accent: var(--gold);       /* the price table; the landing sets its own */
        --plan-on-accent: 0 0% 100%;
        --plan-deep: 240 5% 12%;
        /* Voice sections, high → low. Validated categorical palette (colour-blind safe on adjacent pairs);
           always shown with the voice name next to it, never colour alone. */
        --att-present: #1baf7a; --att-late: #eda100; --att-excused: #2a78d6; --att-absent: #d94f45;
        --voice-1: #2a78d6; --voice-2: #eb6834; --voice-3: #1baf7a;
        --voice-4: #eda100; --voice-5: #e87ba4; --voice-6: #008300;
        --radius: 0.5rem;
    }

    .dark {
        /* Native widgets — the audio player above all — follow the theme instead of
           sitting as a white pill on a black page */
        color-scheme: dark;
        --background: 0 0% 0%;
        --foreground: 240 11% 96%;
        --card: 240 3% 11%;               /* #1C1C1E */
        --card-foreground: 240 11% 96%;
        --popover: 240 3% 11%;
        --popover-foreground: 240 11% 96%;
        --primary: 240 11% 96%;
        --primary-foreground: 240 3% 11%;
        --secondary: 240 3% 18%;
        --secondary-foreground: 240 11% 96%;
        --muted: 240 3% 18%;              /* #2C2C2E */
        --muted-foreground: 240 3% 60%;   /* #98989D */
        --accent: 240 3% 18%;
        --accent-foreground: 240 11% 96%;
        --destructive: 3 100% 61%;        /* #FF453A */
        --destructive-foreground: 0 0% 100%;
        --border: 240 3% 20%;
        --input: 240 3% 26%;
        --ring: 211 100% 60%;
        --gold: 42 72% 58%;
        --att-present: #24c489; --att-late: #f0b021; --att-excused: #4a94ea; --att-absent: #e4655b;
        --voice-1: #3987e5; --voice-2: #d95926; --voice-3: #199e70;
        --voice-4: #c98500; --voice-5: #d55181; --voice-6: #008300;
    }

    * {
        @apply border-border;
    }

    body {
        @apply bg-background text-foreground font-sans;
        font-feature-settings: "rlig" 1, "calt" 1;
        letter-spacing: -0.006em;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
    }

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

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

/* ── Notification shrink animation ── */
@keyframes shrink {
    from { width: 100%; }
    to   { width: 0%; }
}

/* ── Scrollbar hide ── */
/* No scrollbars anywhere: every scrolling surface in the app keeps its gesture and
   loses its gutter, so nothing shifts when a list grows past its box. */
*, .no-scrollbar {
    -ms-overflow-style: none;
    scrollbar-width: none;
}
*::-webkit-scrollbar, .no-scrollbar::-webkit-scrollbar { display: none; }

@layer components {
    /* ── Page typography ── */
    /* Large title, set like the heading of a hymnal */
    .page-title {
        font-family: 'Lora', Georgia, serif;
        font-size: 2rem;
        font-weight: 600;
        letter-spacing: -0.02em;
        line-height: 1.15;
    }
    @media (min-width: 768px) {
        .page-title { font-size: 2.5rem; }
    }

    .page-eyebrow {
        font-size: 0.8125rem;
        font-weight: 500;
        color: hsl(var(--muted-foreground));
    }

    /* A quiet marker for a section: a coloured dot and a plain word */
    /* A quiet label above a section or inside a card. No marker: the weight carries it. */
    .section-dot {
        display: block;
        font-size: 0.8125rem;
        font-weight: 500;
        color: hsl(var(--muted-foreground));
    }

    .section-title {
        font-size: 1.125rem;
        font-weight: 600;
        letter-spacing: -0.01em;
        color: hsl(var(--foreground));
    }

    .back-link {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
        font-size: 0.875rem;
        color: hsl(var(--muted-foreground));
        transition: color 150ms;
    }
    .back-link:hover { color: hsl(var(--foreground)); }

    /* ── Rows ── */
    .row-link {
        display: flex;
        align-items: center;
        gap: 1rem;
        padding: 1rem 1.25rem;
        background: hsl(var(--card));
        transition: background-color 120ms ease;
        cursor: pointer;
    }
    .row-link:hover { background: hsl(var(--accent) / 0.5); }

    /* ── Forms ── */
    .field-label {
        display: block;
        font-size: 0.875rem;
        font-weight: 600;
        color: hsl(var(--foreground));
    }

    .field-hint {
        font-size: 0.8125rem;
        line-height: 1.45;
        color: hsl(var(--muted-foreground));
    }

    .field-input {
        display: flex;
        width: 100%;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--input));
        background: hsl(var(--card));
        padding: 0.5625rem 0.75rem;
        font-size: 1rem;
        font-family: inherit;
        color: hsl(var(--foreground));
        transition: border-color 150ms, box-shadow 150ms;
        outline: none;
        line-height: 1.5;
    }
    .field-input::placeholder { color: hsl(var(--muted-foreground) / 0.6); }
    .field-input:focus {
        border-color: hsl(var(--ring));
        box-shadow: 0 0 0 3px hsl(var(--ring) / 0.15);
    }
    .field-input-sm { padding: 0.375rem 0.625rem; font-size: 0.875rem; }
    .field-input-lg { padding: 0.75rem 1rem; font-size: 1.0625rem; }

    .field-select {
        appearance: none;
        cursor: pointer;
        padding-right: 2rem;
        text-overflow: ellipsis;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 0.625rem center;
    }
    .field-select.is-set { border-color: hsl(var(--foreground) / 0.45); }

    .file-input {
        display: block;
        width: 100%;
        font-size: 0.875rem;
        color: hsl(var(--muted-foreground));
    }
    .file-input::file-selector-button {
        margin-right: 0.875rem;
        padding: 0.5rem 1rem;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--border));
        background: hsl(var(--background));
        color: hsl(var(--foreground));
        font-family: inherit;
        font-size: 0.875rem;
        font-weight: 500;
        cursor: pointer;
        transition: background-color 150ms;
    }
    .file-input::file-selector-button:hover { background: hsl(var(--accent)); }

    .form-footer {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding-top: 1.5rem;
        border-top: 1px solid hsl(var(--border) / 0.6);
    }

    /* Long forms keep Save within thumb reach, above the mobile tab bar */
    .form-footer.is-sticky {
        position: sticky;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 5.5rem);
        z-index: 30;
        margin-inline: -1.25rem;
        padding: 0.875rem 1.25rem;
        background: hsl(var(--background) / 0.9);
        -webkit-backdrop-filter: blur(12px);
        backdrop-filter: blur(12px);
    }
    @media (min-width: 768px) {
        .form-footer.is-sticky { bottom: 0; }
    }

    /* ── Filter chips: a native <select> laid over a chip, so phones open their own picker ── */
    .chip-row {
        display: flex;
        gap: 0.5rem;
        overflow-x: auto;
        margin-inline: -1.25rem;
        padding: 0.125rem 1.25rem;
        scrollbar-width: none;
    }
    .chip-row::-webkit-scrollbar { display: none; }
    @media (min-width: 1024px) {
        .chip-row.lg-inline { margin-inline: 0; padding-inline: 0; }
    }

    .filter-chip {
        position: relative;
        display: inline-flex;
        flex-shrink: 0;
        align-items: center;
        gap: 0.375rem;
        height: 2.125rem;
        padding: 0 0.75rem;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--border));
        background: hsl(var(--card));
        font-size: 0.875rem;
        color: hsl(var(--foreground) / 0.85);
        white-space: nowrap;
        transition: background-color 120ms, color 120ms, border-color 120ms;
    }
    .filter-chip:hover { background: hsl(var(--accent) / 0.6); }
    .filter-chip:focus-within { box-shadow: 0 0 0 3px hsl(var(--ring) / 0.35); }
    .filter-chip.is-set {
        background: hsl(var(--foreground));
        border-color: hsl(var(--foreground));
        color: hsl(var(--background));
    }
    .filter-chip-select {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
        cursor: pointer;
        font-size: 16px; /* no zoom-on-focus on iOS */
    }

    /* The invitation panel opens when it is wanted, and stays out of the way otherwise */
    .invite-panel > summary::-webkit-details-marker { display: none; }
    .invite-panel > summary:hover { background: hsl(var(--accent) / 0.35); }
    .invite-panel[open] .invite-caret { transform: rotate(180deg); }
    .invite-caret { transition: transform 150ms; }

    /* Native disclosure: no JavaScript, keyboard and screen readers get it for free.
       Everything starts closed; the caret is a lucide chevron that turns as it opens. */
    .disclosure > summary,
    .disclosure-group > summary {
        cursor: pointer;
        list-style: none;
        user-select: none;
    }
    .disclosure > summary::-webkit-details-marker,
    .disclosure-group > summary::-webkit-details-marker { display: none; }
    .disclosure-caret { transition: transform 150ms ease; opacity: 0.55; }
    .disclosure[open] > summary .disclosure-caret,
    .disclosure-group[open] > summary .disclosure-caret { transform: rotate(90deg); opacity: 1; }

    /* The section's own line: quiet, like every other eyebrow on the page */
    .disclosure-head {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.125rem 0;
        border-radius: 0.5rem;
    }
    .disclosure-head:focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: 3px; }

    /* One audience per row, inside the card: name left, what it holds right */
    .disclosure-row {
        display: flex;
        align-items: center;
        gap: 0.625rem;
        padding: 0.8125rem 1rem;
        transition: background-color 120ms;
    }
    .disclosure-row:hover { background: hsl(var(--accent) / 0.4); }
    .disclosure-row:focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: -2px; }
    .disclosure-group[open] > .disclosure-row { background: hsl(var(--accent) / 0.3); }
    .disclosure-name {
        flex: 1;
        min-width: 0;
        font-size: 0.9375rem;
        color: hsl(var(--foreground));
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .disclosure-count {
        font-size: 0.75rem;
        font-variant-numeric: tabular-nums;
        color: hsl(var(--muted-foreground));
        min-width: 1.25rem;
        text-align: right;
    }

    /* Open rows sit on a slightly recessed ground, so the nesting reads without indentation */
    .disclosure-body {
        border-top: 1px solid hsl(var(--border) / 0.7);
        background: hsl(var(--muted) / 0.35);
    }
    .disclosure-body > * + * { border-top: 1px solid hsl(var(--border) / 0.6); }

    .list-scroll {
        max-height: min(70vh, 46rem);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    [data-nested-row][hidden] { display: none; }

    /* ── Choice chips (multi-select checkboxes) ── */
    .chip { display: inline-flex; cursor: pointer; }
    .chip[hidden] { display: none; }
    .chip-face {
        display: inline-flex;
        align-items: center;
        border: 1px solid hsl(var(--border));
        border-radius: 0.5rem;
        padding: 0.3125rem 0.8125rem;
        font-size: 0.875rem;
        line-height: 1.25rem;
        color: hsl(var(--foreground) / 0.8);
        background: hsl(var(--card));
        user-select: none;
        transition: background-color 120ms, color 120ms, border-color 120ms;
    }
    .chip:hover .chip-face { color: hsl(var(--foreground)); border-color: hsl(var(--foreground) / 0.35); }
    /* A chip face used on its own as a link (public profile: the choir's social links) */
    a.chip-face { gap: 0.375rem; }
    a.chip-face:hover { color: hsl(var(--foreground)); border-color: hsl(var(--foreground) / 0.35); }
    .peer:checked + .chip-face {
        background: hsl(var(--foreground));
        border-color: hsl(var(--foreground));
        color: hsl(var(--background));
    }
    .peer:focus-visible + .chip-face { box-shadow: 0 0 0 3px hsl(var(--ring) / 0.4); }

    /* ── Attendance charts: plain bars, one measure, no decoration ── */
    .chart-scroll {
        overflow-x: auto;
        scrollbar-width: none;
        margin-inline: -0.25rem;
        padding: 0 0.25rem 0.25rem;
    }
    .chart-scroll::-webkit-scrollbar { display: none; }
    .chart-columns { display: flex; align-items: flex-end; gap: 0.375rem; min-height: 11rem; }
    .chart-column {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 0.375rem;
        flex: 0 0 2.25rem;
        text-decoration: none;
    }
    .chart-track {
        display: flex;
        align-items: flex-end;
        width: 100%;
        height: 8rem;
        border-radius: 0.25rem;
        background: hsl(var(--secondary) / 0.8);
        overflow: hidden;
    }
    .chart-bar {
        display: block;
        width: 100%;
        border-radius: 0.25rem;
        background: var(--att-present);
        transition: background-color 120ms;
    }
    .chart-column:hover .chart-bar { filter: brightness(0.92); }
    .chart-value { font-size: 0.6875rem; font-variant-numeric: tabular-nums; color: hsl(var(--muted-foreground)); }
    .chart-tick { font-size: 0.625rem; color: hsl(var(--muted-foreground)); white-space: nowrap; }

    .chart-seg {
        position: relative;
        flex: 1 1 0;
        min-width: 0.5rem;
        height: 100%;
        border-radius: 0.1875rem;
        background: hsl(var(--foreground) / 0.06);
    }

    /* A year of rolls, one square per day */
    .activity-grid { display: flex; gap: 3px; padding-bottom: 0.25rem; }
    .activity-months { display: flex; gap: 3px; }
    .activity-month {
        width: 0.75rem;
        font-size: 0.625rem;
        line-height: 1;
        color: hsl(var(--muted-foreground));
        white-space: nowrap;
        overflow: visible;
    }
    .activity-week { display: grid; grid-template-rows: repeat(7, 0.75rem); gap: 3px; }
    .activity-cell {
        position: relative;
        width: 0.75rem;
        height: 0.75rem;
        border-radius: 0.1875rem;
        background: hsl(var(--foreground) / 0.06);
    }
    .activity-cell.is-outside { background: none; }
    .activity-cell:hover { outline: 1px solid hsl(var(--foreground) / 0.35); outline-offset: 1px; }
    .activity-cell.is-outside:hover { outline: none; }

    /* One colour per state: every present cell reads the same, on every row */
    .att-present { background: var(--att-present); }
    .att-late { background: var(--att-late); }
    .att-excused { background: var(--att-excused); }
    .att-absent { background: var(--att-absent); }
    .att-blank {
        background: repeating-linear-gradient(45deg, transparent, transparent 3px,
                    hsl(var(--foreground) / 0.10) 3px, hsl(var(--foreground) / 0.10) 4px);
    }

    .chart-key { width: 0.75rem; height: 0.75rem; border-radius: 0.1875rem; display: inline-block; }

    /* Hover tells you which event it is — no click needed */
    .chart-tip {
        position: absolute;
        bottom: calc(100% + 0.5rem);
        left: 50%;
        transform: translateX(-50%) translateY(0.25rem);
        z-index: 30;
        max-width: 16rem;
        width: max-content;
        padding: 0.375rem 0.625rem;
        border-radius: 0.375rem;
        background: hsl(var(--foreground));
        color: hsl(var(--background));
        font-size: 0.75rem;
        line-height: 1.25;
        white-space: normal;
        opacity: 0;
        pointer-events: none;
        transition: opacity 120ms, transform 120ms;
    }
    .chart-seg:hover .chart-tip,
    .chart-column:hover .chart-tip,
    .chart-cell:hover .chart-tip,
    .chart-seg:focus-visible .chart-tip {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
    .chart-column { position: relative; }

    .chart-row { display: flex; align-items: center; gap: 0.75rem; }
    .chart-row-name { flex: 0 0 9rem; font-size: 0.8125rem; color: hsl(var(--foreground)); }
    .chart-row-track {
        display: flex;
        gap: 2px;
        flex: 1;
        height: 1.125rem;
        overflow: visible;
    }
    .chart-row-track .chart-bar { height: 100%; }
    .chart-row-value { flex: 0 0 2.75rem; text-align: right; font-size: 0.8125rem; color: hsl(var(--muted-foreground)); }
    @media (max-width: 640px) {
        .chart-row-name { flex-basis: 6.5rem; }
    }

    /* ── Roll call: one segmented control per member, on a single line ── */
    .roll-track {
        display: flex;
        overflow-x: auto;
        scrollbar-width: none;
        margin-inline: -0.25rem;
        padding: 0.125rem 0.25rem;
    }
    .roll-track::-webkit-scrollbar { display: none; }
    .roll-options {
        display: inline-flex;
        flex-shrink: 0;
        align-items: center;
        gap: 0.125rem;
        padding: 0.125rem;
        border: 1px solid hsl(var(--border));
        border-radius: 0.5rem;
        background: hsl(var(--secondary) / 0.7);
    }
    .roll-options label { display: inline-flex; }
    .roll-option {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0.25rem 0.625rem;
        border-radius: 0.375rem;
        font-size: 0.8125rem;
        line-height: 1.25rem;
        white-space: nowrap;
        color: hsl(var(--muted-foreground));
        cursor: pointer;
        user-select: none;
        transition: background-color 120ms, color 120ms;
    }
    .roll-option:hover { color: hsl(var(--foreground)); }
    .peer:checked + .roll-option {
        background: hsl(var(--card));
        color: hsl(var(--foreground));
        box-shadow: 0 1px 2px hsl(var(--foreground) / 0.08);
    }
    .peer:checked + .roll-option.is-clear { background: none; box-shadow: none; color: hsl(var(--muted-foreground)); }
    .peer:focus-visible + .roll-option { box-shadow: 0 0 0 3px hsl(var(--ring) / 0.4); }

    /* ── Buttons ── */
    .btn-primary, .btn-outline, .btn-ghost, .btn-danger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        padding: 0.5rem 1rem;
        border-radius: 0.5rem;
        border: 1px solid transparent;
        font-size: 0.9375rem;
        font-weight: 500;
        line-height: 1.25rem;
        white-space: nowrap;
        cursor: pointer;
        transition: background-color 150ms, color 150ms, border-color 150ms;
    }
    .btn-primary { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); font-weight: 500; }
    .btn-primary:hover { background: hsl(var(--primary) / 0.88); }
    .btn-outline { border-color: hsl(var(--border)); background: hsl(var(--card)); color: hsl(var(--foreground)); }
    .btn-outline:hover { background: hsl(var(--accent) / 0.6); }
    .btn-ghost { color: hsl(var(--muted-foreground)); padding-left: 0.25rem; padding-right: 0.25rem; }
    .btn-ghost:hover { color: hsl(var(--foreground)); }
    .btn-danger { border-color: hsl(var(--destructive) / 0.4); color: hsl(var(--destructive)); background: transparent; }
    .btn-danger:hover { background: hsl(var(--destructive)); border-color: hsl(var(--destructive)); color: hsl(var(--destructive-foreground)); }
    .btn-block { width: 100%; padding-top: 0.75rem; padding-bottom: 0.75rem; }
    .btn-ghost.btn-block { padding-left: 1.125rem; padding-right: 1.125rem; }

    .icon-button {
        height: 2.25rem;
        width: 2.25rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border-radius: 0.5rem;
        color: hsl(var(--muted-foreground));
        transition: background-color 150ms, color 150ms;
    }
    .icon-button:hover { background: hsl(var(--muted)); color: hsl(var(--foreground)); }
    .icon-button.is-danger:hover { background: hsl(var(--destructive) / 0.1); color: hsl(var(--destructive)); }

    .danger-zone {
        display: flex;
        flex-direction: column;
        gap: 1rem;
        padding: 1.25rem;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--destructive) / 0.25);
    }
    @media (min-width: 640px) {
        .danger-zone { flex-direction: row; align-items: center; justify-content: space-between; }
    }

    .divider {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        font-size: 0.8125rem;
        color: hsl(var(--muted-foreground));
    }
    .divider::before, .divider::after {
        content: "";
        flex: 1;
        height: 1px;
        background: hsl(var(--border));
    }

    /* ── Badges & pills ── */
    .badge-muted, .badge-outline, .badge-solid {
        display: inline-flex;
        align-items: center;
        border-radius: 0.5rem;
        padding: 0.125rem 0.5rem;
        font-size: 0.6875rem;
        font-weight: 500;
        line-height: 1rem;
        white-space: nowrap;
    }
    .badge-muted { background: hsl(var(--muted)); color: hsl(var(--muted-foreground)); }
    .badge-outline { border: 1px solid hsl(var(--border)); color: hsl(var(--muted-foreground)); }
    .badge-solid { background: hsl(var(--foreground)); color: hsl(var(--background)); min-width: 1.125rem; justify-content: center; padding: 0 0.3125rem; }

    .filter-pill {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--foreground) / 0.25);
        padding: 0.25rem 0.625rem;
        font-size: 0.8125rem;
        color: hsl(var(--foreground));
        transition: background-color 120ms;
    }
    .filter-pill:hover { background: hsl(var(--accent)); }

    .tag-link {
        display: inline-flex;
        align-items: center;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--border));
        padding: 0.25rem 0.75rem;
        font-size: 0.875rem;
        color: hsl(var(--foreground) / 0.85);
        transition: background-color 120ms, border-color 120ms;
    }
    .tag-link:hover { background: hsl(var(--accent) / 0.6); border-color: hsl(var(--foreground) / 0.3); }

    .detail-link {
        text-decoration: underline;
        text-decoration-color: hsl(var(--border));
        text-underline-offset: 4px;
        transition: text-decoration-color 150ms;
    }
    .detail-link:hover { text-decoration-color: hsl(var(--foreground)); }

    /* ── Voices ── */
    .voice-badge {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 1.75rem;
        height: 1.5rem;
        padding: 0 0.375rem;
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--border));
        font-size: 0.6875rem;
        font-weight: 600;
        letter-spacing: 0.02em;
        color: hsl(var(--foreground) / 0.8);
    }

    /* The key sits under the bar, each item as wide as its own segment, so a section's
       name is centred on the colour it belongs to. Too narrow to read on a phone, so
       there it falls back to a plain wrapping list. */
    .voice-keys { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; }
    @media (min-width: 640px) {
        .voice-keys { flex-wrap: nowrap; gap: 2px; }
        .voice-keys > .voice-key { flex-basis: 0; justify-content: center; }
    }

    .voice-key {
        display: inline-flex;
        align-items: center;
        justify-content: flex-start;
        gap: 0.4375rem;
        flex: 0 1 auto;
        min-width: 0;
        padding-top: 0.375rem;
        font-size: 0.8125rem;
        line-height: 1.25rem;
        color: hsl(var(--muted-foreground));
        transition: color 120ms;
    }
    .voice-key:hover { color: hsl(var(--foreground)); }
    .voice-key.is-active { color: hsl(var(--foreground)); font-weight: 500; }
    .voice-key.is-active .voice-key-dot { box-shadow: 0 0 0 3px hsl(var(--foreground) / 0.12); }
    .voice-key-dot { width: 0.5rem; height: 0.5rem; border-radius: 9999px; flex-shrink: 0; }
    .voice-key-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .voice-key-count { font-variant-numeric: tabular-nums; font-weight: 600; color: hsl(var(--foreground)); }

    /* The section's own colour, carried by its name rather than a dot */
    .voice-name-0 { color: var(--voice-1); }
    .voice-name-1 { color: var(--voice-2); }
    .voice-name-2 { color: var(--voice-3); }
    .voice-name-3 { color: var(--voice-4); }
    .voice-name-4 { color: var(--voice-5); }
    .voice-name-5 { color: var(--voice-6); }

    .voice-tone-0 { background: var(--voice-1); }
    .voice-tone-1 { background: var(--voice-2); }
    .voice-tone-2 { background: var(--voice-3); }
    .voice-tone-3 { background: var(--voice-4); }
    .voice-tone-4 { background: var(--voice-5); }
    .voice-tone-5 { background: var(--voice-6); }

    /* Stacked section bar: 2px surface gaps between segments, 4px rounded ends */
    .voice-bar { display: flex; gap: 2px; height: 0.625rem; }
    .voice-bar > span { border-radius: 2px; min-width: 4px; }
    .voice-bar > span:first-child { border-top-left-radius: 4px; border-bottom-left-radius: 4px; }
    .voice-bar > span:last-child { border-top-right-radius: 4px; border-bottom-right-radius: 4px; }

    /* ── Grouped form rows: label left, value right, hairlines between ── */
    .form-card {
        border-radius: 0.5rem;
        border: 1px solid hsl(var(--border) / 0.8);
        background: hsl(var(--card));
        overflow: hidden;
    }
    .form-card > * + * { border-top: 1px solid hsl(var(--border) / 0.7); }

    .form-row {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        min-height: 3rem;
        padding: 0.5rem 1rem;
    }
    .form-row:focus-within { background: hsl(var(--accent) / 0.35); }
    .row-label {
        width: 6rem;
        flex-shrink: 0;
        font-size: 0.9375rem;
        color: hsl(var(--foreground));
    }
    @media (min-width: 640px) { .row-label { width: 8rem; } }

    .row-input {
        flex: 1;
        min-width: 0;
        border: 0;
        background: transparent;
        padding: 0.25rem 0;
        font-family: inherit;
        font-size: 0.9375rem;
        color: hsl(var(--foreground));
        text-align: right;
        outline: none;
    }
    .row-input::placeholder { color: hsl(var(--muted-foreground) / 0.7); }
    .row-input.is-title { text-align: left; font-size: 1.0625rem; font-weight: 600; }
    .row-input.is-select {
        appearance: none;
        cursor: pointer;
        text-align: right;
        direction: rtl;
        padding-right: 1.125rem;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right center;
    }
    .row-input.is-select > option { direction: ltr; }
    .row-stacked { display: block; padding: 0.75rem 1rem; }
    .row-stacked .row-input { text-align: left; }

    /* ── Segmented control (iOS) ── */
    .segmented {
        display: inline-grid;
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        gap: 0.125rem;
        padding: 0.1875rem;
        border-radius: 0.5rem;
        background: hsl(var(--muted));
    }
    .segmented > a {
        padding: 0.375rem 1rem;
        border-radius: 0.375rem;
        font-size: 0.8125rem;
        font-weight: 500;
        text-align: center;
        white-space: nowrap;
        color: hsl(var(--foreground) / 0.7);
        transition: background-color 150ms, color 150ms;
    }
    .segmented > a:hover { color: hsl(var(--foreground)); }
    .segmented > a[aria-current="page"] {
        background: hsl(var(--card));
        color: hsl(var(--foreground));
        box-shadow: 0 1px 2px rgb(0 0 0 / 0.08), 0 0 0 0.5px rgb(0 0 0 / 0.04);
    }

    /* ── Calendar leaf: the date of an event, like a page torn from a liturgical calendar ── */
    .date-leaf {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 0.125rem;
        width: 3.5rem;
        height: 3.75rem;
        flex-shrink: 0;
        border-radius: 0.5rem;
        background: hsl(var(--card));
        border: 1px solid hsl(var(--border));
    }
    .date-leaf-month { font-size: 0.625rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: hsl(var(--gold)); line-height: 1; }
    .date-leaf-day { font-family: 'Lora', Georgia, serif; font-size: 1.5rem; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; color: hsl(var(--foreground)); }
    .date-leaf-weekday { font-size: 0.625rem; color: hsl(var(--muted-foreground)); line-height: 1; }
    .date-leaf.is-lg { width: 4.5rem; height: 5rem; }
    .date-leaf.is-lg .date-leaf-day { font-size: 2rem; }
    .date-leaf.is-lg .date-leaf-month, .date-leaf.is-lg .date-leaf-weekday { font-size: 0.6875rem; }

    /* ── Event status ── */
    .status-badge {
        font-size: 0.75rem;
        font-weight: 500;
        line-height: 1.25rem;
        white-space: nowrap;
        color: hsl(var(--muted-foreground));
    }
    .status-next { color: hsl(var(--gold)); font-weight: 600; }
    .status-cancelled { color: hsl(var(--destructive) / 0.85); }

    /* ── Cards ── */
    .event-card {
        display: flex;
        gap: 1rem;
        padding: 1rem;
        border-radius: 0.5rem;
        background: hsl(var(--card));
        border: 1px solid hsl(var(--border) / 0.8);
        transition: background-color 120ms, box-shadow 150ms;
    }
    .event-card:hover { box-shadow: 0 2px 10px rgb(0 0 0 / 0.06); }

    /* Public pages share the signed-in canvas, so both sides of the app line up */
    .public-shell {
        max-width: 72rem;
        margin-inline: auto;
        padding-inline: 1.25rem;
    }
    @media (min-width: 1536px) {
        .public-shell { max-width: 80rem; }
    }

    /* The calendar as a board: one column per month. The whole board scrolls in both
       directions — down through a month, across to the next — and each month name stays
       pinned while its own column is in view. Columns keep their width whether there is
       one month or twelve. */
    .month-board {
        display: flex;
        align-items: flex-start;
        gap: 1rem;
        max-height: min(72vh, 52rem);
        overflow: auto;
        overscroll-behavior: contain;
        scroll-snap-type: x proximity;
        margin-inline: -1.25rem;
        padding: 0 1.25rem 0.5rem;
    }
    .month-board > * {
        flex: 0 0 min(23rem, 86vw);
        scroll-snap-align: start;
    }
    @media (min-width: 768px) {
        .month-board { margin-inline: 0; padding-inline: 0.125rem; }
    }
    .month-head {
        position: sticky;
        top: 0;
        z-index: 1;
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
        padding: 0.375rem 0 0.5rem;
        background: hsl(var(--background));
    }
    .month-column { display: grid; gap: 0.75rem; align-content: start; }

    .event-card.is-cancelled .event-card-title { text-decoration: line-through; color: hsl(var(--muted-foreground)); }

    .program { counter-reset: program; }
    .program > [data-nested-row]:not([hidden]), .program > .program-row { counter-increment: program; }
    .program-number::before {
        content: counter(program);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 1.5rem;
        height: 1.5rem;
        border-radius: 9999px;
        background: hsl(var(--muted));
        font-size: 0.75rem;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
        color: hsl(var(--foreground) / 0.75);
    }

    /* ── Price table ──────────────────────────────────────────────────────────
       One markup, two homes: the landing and a choir's settings. Both prices are
       in the page and the `plan-period` Stimulus controller shows one, so the
       monthly/yearly switch never costs a request. */
    .plan-switch { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 0.125rem; padding: 0.1875rem; border-radius: 0.5rem; background: hsl(var(--muted)); }
    .plan-switch > button {
        padding: 0.4375rem 1.125rem; border-radius: 0.375rem; font-size: 0.8125rem; font-weight: 500;
        white-space: nowrap; color: hsl(var(--foreground) / 0.7); transition: background-color 150ms, color 150ms;
    }
    .plan-switch > button:hover { color: hsl(var(--foreground)); }
    .plan-switch > button[aria-current="page"] {
        background: hsl(var(--card)); color: hsl(var(--foreground));
        box-shadow: 0 1px 2px rgb(0 0 0 / 0.08), 0 0 0 0.5px rgb(0 0 0 / 0.04);
    }

    /* The price table (shared/_plans). Its colours are variables so the landing
       can carry them in its own brand colour: --plan-accent (ribbon, featured
       price, ticks), --plan-deep (the featured card and the sur-mesure banner). */
    .plan-grid { display: grid; gap: 1.25rem; align-items: stretch; padding-top: 0.75rem; }
    @media (min-width: 900px) { .plan-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
    .plan-card {
        position: relative; display: grid; grid-template-rows: auto auto 1fr auto; gap: 1.25rem;
        padding: 1.75rem 1.5rem 1.5rem; border: 1px solid hsl(var(--border)); border-radius: var(--radius);
        background: hsl(var(--card));
    }
    .plan-card.is-featured {
        background: hsl(var(--plan-deep)); border-color: hsl(var(--plan-deep)); color: #fff;
        box-shadow: 0 28px 56px -32px hsl(var(--plan-deep) / 0.8);
    }
    .dark .plan-card.is-featured { border-color: hsl(var(--plan-accent) / 0.5); }
    .plan-card.is-current { border-color: hsl(var(--foreground)); }
    .plan-ribbon {
        position: absolute; top: -0.75rem; left: 1.5rem; padding: 0.25rem 0.625rem; border-radius: 0.375rem;
        background: hsl(var(--plan-accent)); color: hsl(var(--plan-on-accent));
        font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    }
    .plan-name { font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: hsl(var(--muted-foreground)); }
    .plan-tagline { font-size: 0.875rem; line-height: 1.55; color: hsl(var(--muted-foreground)); }
    @media (min-width: 900px) { .plan-tagline { min-height: 2.7em; } }
    .plan-price { font-size: 1.875rem; font-weight: 700; letter-spacing: -0.03em; color: hsl(var(--foreground)); white-space: nowrap; margin-top: 0.75rem; }
    .plan-per { font-size: 0.8125rem; font-weight: 400; letter-spacing: 0; color: hsl(var(--muted-foreground)); margin-left: 0.25rem; }
    .plan-card.is-featured .plan-name { color: rgb(255 255 255 / 0.9); }
    .plan-card.is-featured .plan-tagline, .plan-card.is-featured .plan-per { color: rgb(255 255 255 / 0.66); }
    .plan-card.is-featured .plan-price { color: hsl(var(--plan-accent)); }
    .plan-features { display: grid; gap: 0.6875rem; align-content: start; padding-top: 1.25rem; border-top: 1px solid hsl(var(--border)); }
    .plan-card.is-featured .plan-features { border-color: rgb(255 255 255 / 0.14); }
    /* Each feature carries a tick drawn in CSS, in the accent colour */
    .plan-feature { position: relative; padding-left: 1.625rem; font-size: 0.875rem; line-height: 1.5; color: hsl(var(--foreground) / 0.88); }
    .plan-feature::before {
        content: ""; position: absolute; left: 0.25rem; top: 0.25rem; width: 0.4375rem; height: 0.75rem;
        border: solid hsl(var(--plan-accent)); border-width: 0 2px 2px 0; transform: rotate(45deg);
    }
    .plan-card.is-featured .plan-feature { color: rgb(255 255 255 / 0.88); }
    .plan-foot { font-size: 0.8125rem; font-weight: 600; color: hsl(var(--foreground)); }
    .plan-card.is-featured .plan-foot { color: #fff; }

    /* Sur mesure: copy, not a Plan, set as a dark banner under the three */
    .plan-custom {
        display: grid; gap: 1.5rem; padding: 1.75rem; border-radius: var(--radius);
        background: hsl(var(--plan-deep)); color: #fff;
    }
    @media (min-width: 900px) { .plan-custom { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 3rem; padding: 2rem 2.25rem; } }
    .plan-custom-name { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.01em; }
    .plan-custom-tagline { font-size: 0.875rem; color: rgb(255 255 255 / 0.66); margin-top: 0.25rem; }
    .plan-custom-features { display: grid; gap: 0.5rem 2rem; margin-top: 1.25rem; }
    @media (min-width: 640px) { .plan-custom-features { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
    .plan-custom-features .plan-feature { color: rgb(255 255 255 / 0.88); }
    .plan-custom-side { display: grid; gap: 0.75rem; justify-items: start; }
    @media (min-width: 900px) { .plan-custom-side { justify-items: end; text-align: right; } }
    .plan-custom-price { font-size: 1.5rem; font-weight: 700; color: hsl(var(--plan-accent)); }
    .plan-custom-cta {
        display: inline-flex; align-items: center; justify-content: center; padding: 0.625rem 1.25rem; border-radius: var(--radius);
        background: hsl(var(--plan-accent)); color: hsl(var(--plan-on-accent)); font-size: 0.875rem; font-weight: 600;
        transition: filter 150ms;
    }
    .plan-custom-cta:hover { filter: brightness(1.06); }

    /* ── Landing ──────────────────────────────────────────────────────────────
       The landing is the only page allowed its own skin, because it welcomes
       people who have never seen the app. White ground, warm tinted bands, and
       one brand orange, used boldly the way Genuka uses its own: the buttons,
       a highlighted phrase in the headline, the eyebrows, the programme's cues,
       the price table and one full band of colour at the end. Lora (the app's
       own face) for display; italic Lora only for words that are sung.

       Orange has three strengths because contrast needs them:
       · --lp-accent      fills (buttons, ribbon, closing band), with dark text
                          (--lp-on-accent) — white on this orange fails contrast;
       · --lp-accent-ink  large text (the headline's highlight);
       · --lp-accent-text small text (eyebrows, cues).
       --lp-tint is the ground of every other band, --lp-deep the dark surfaces
       (the featured plan, the sur-mesure banner, the footer). The data palettes
       (--voice-*, --att-*) stay on data only. */
    body.landing { background: hsl(var(--background)); }
    /* The app's dark theme is true black, which makes a whole marketing page feel
       like a hole. On the landing only, lift the surfaces to a soft charcoal. The
       tokens are redefined on <body>, so the shared navbar follows along. */
    .dark body.landing, .dark .landing-page {
        --background: 240 6% 8%;
        --card: 240 6% 12%;
        --muted: 240 6% 14%;
        --border: 240 5% 20%;
        --input: 240 5% 26%;
    }

    /* On <body>, not .landing-page, so the navbar's buttons get them too */
    body.landing {
        --lp-accent: 25 95% 53%;          /* #F97316 */
        --lp-accent-ink: 21 90% 48%;      /* #EA580C */
        --lp-accent-text: 17 88% 40%;     /* #C2410C */
        --lp-on-accent: 20 60% 9%;
        --lp-tint: 30 100% 97%;
        --lp-deep: 24 40% 9%;
        --plan-accent: var(--lp-accent);
        --plan-on-accent: var(--lp-on-accent);
        --plan-deep: var(--lp-deep);
    }
    .landing-page {
        overflow-x: clip;
        background-color: hsl(var(--background));
    }

    .dark body.landing {
        --lp-accent: 25 95% 55%;
        --lp-accent-ink: 27 96% 61%;
        --lp-accent-text: 31 97% 70%;
        --lp-tint: 24 18% 11%;
        --lp-deep: 24 22% 14%;
    }

    .lp-shell { max-width: 76rem; margin-inline: auto; padding-inline: 1.25rem; }
    @media (min-width: 720px) { .lp-shell { padding-inline: 2.5rem; } }
    @media (min-width: 1600px) { .lp-shell { max-width: 84rem; } }

    .lp-section { padding-block: 4.5rem; }
    @media (min-width: 900px) { .lp-section { padding-block: 7rem; } }

    /* Sections are delimited by a full-bleed hairline; overflow-x: clip on the
       page keeps the 100vw rule from causing a scrollbar. */
    .lp-sep { position: relative; }
    .lp-sep::before {
        content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
        width: 100vw; height: 1px; background: hsl(var(--border));
    }

    /* A tinted band, full-bleed without extra markup: the shadow paints the
       colour out to the viewport's edges and the clip keeps it to the band */
    .lp-band { background: hsl(var(--lp-tint)); box-shadow: 0 0 0 100vmax hsl(var(--lp-tint)); clip-path: inset(0 -100vmax); }

    /* ── Type ── */
    .lp-eyebrow {
        font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.16em;
        text-transform: uppercase; color: hsl(var(--lp-accent-text));
    }
    .lp-display, .lp-head {
        font-family: 'Lora', Georgia, serif; font-weight: 500; font-style: normal;
        color: hsl(var(--foreground)); text-wrap: balance;
    }
    .lp-display { font-size: clamp(2.5rem, 6vw, 4.375rem); line-height: 1.05; letter-spacing: -0.03em; }
    .lp-display mark { background: none; color: hsl(var(--lp-accent-ink)); }
    .lp-head { font-size: clamp(1.75rem, 3.3vw, 2.625rem); line-height: 1.12; letter-spacing: -0.02em; }
    .lp-lead { font-size: clamp(1.0625rem, 1.5vw, 1.1875rem); line-height: 1.6; color: hsl(var(--muted-foreground)); text-wrap: pretty; }
    .lp-body { font-size: 1.0625rem; line-height: 1.65; color: hsl(var(--muted-foreground)); text-wrap: pretty; }
    .lp-note { font-size: 0.8125rem; line-height: 1.6; color: hsl(var(--muted-foreground)); }

    /* A section's header: rubric, heading, then the sentence that explains it.
       On a wide screen the sentence sits to the right, level with the heading's
       last line, so the panel below starts sooner. */
    .lp-intro { display: grid; gap: 0.875rem; margin-bottom: 2.5rem; }
    @media (min-width: 960px) {
        .lp-intro { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: 4rem; margin-bottom: 3.5rem; }
        .lp-intro > .lp-eyebrow { grid-column: 1 / -1; }
        .lp-intro > .lp-head { grid-column: 1; }
        .lp-intro > .lp-body { grid-column: 2; align-self: end; }
    }

    /* The other rhythm: the header beside its content instead of above it, for
       the sections whose content is a column (the import mapping, questions). */
    .lp-split { display: grid; gap: 2rem; }
    .lp-split > .lp-intro { margin-bottom: 0; }
    @media (min-width: 960px) {
        .lp-split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 4rem; align-items: start; }
        .lp-split > .lp-intro { grid-template-columns: minmax(0, 1fr); }
        .lp-split > .lp-intro > .lp-body { grid-column: 1; }
    }

    /* ── Buttons ── */
    .lp-cta {
        display: inline-flex; align-items: center; justify-content: center;
        padding: 0.875rem 1.625rem; border-radius: var(--radius);
        background: hsl(var(--lp-accent)); color: hsl(var(--lp-on-accent)); font-size: 0.9375rem; font-weight: 700;
        box-shadow: 0 1px 0 hsl(var(--lp-accent-ink)), 0 10px 24px -14px hsl(var(--lp-accent) / 0.9);
        transition: filter 150ms, transform 150ms;
    }
    .lp-cta:hover { filter: brightness(1.05); }
    .lp-cta:active { transform: translateY(1px); }
    /* On the orange band the main button turns dark */
    .lp-cta.is-ink { background: hsl(var(--lp-deep)); color: #fff; box-shadow: none; }
    .lp-second {
        display: inline-flex; align-items: center; justify-content: center;
        padding: 0.875rem 1.5rem; border-radius: var(--radius);
        border: 1px solid hsl(var(--foreground) / 0.2); background: hsl(var(--card));
        font-size: 0.9375rem; font-weight: 600; color: hsl(var(--foreground));
        transition: background-color 150ms, border-color 150ms;
    }
    .lp-second:hover { background: hsl(var(--muted)); border-color: hsl(var(--foreground) / 0.35); }
    .lp-second.is-clear { background: transparent; border-color: hsl(var(--lp-on-accent) / 0.35); color: hsl(var(--lp-on-accent)); }
    .lp-second.is-clear:hover { background: hsl(var(--lp-on-accent) / 0.08); }
    .lp-cta.is-sm, .lp-second.is-sm { padding: 0.5rem 0.875rem; font-size: 0.875rem; }
    .lp-cta:focus-visible, .lp-second:focus-visible, .lp-faq-item > summary:focus-visible {
        outline: 2px solid hsl(var(--foreground)); outline-offset: 3px;
    }
    /* The two calls belong on one row. On a phone they tighten rather than stack:
       a stacked pair reads as two decisions, a row reads as one with a default. */
    .lp-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
    @media (max-width: 480px) {
        .lp-actions { flex-wrap: nowrap; }
        .lp-actions > .lp-cta, .lp-actions > .lp-second { padding-inline: 1rem; font-size: 0.875rem; }
    }

    /* ── Top bar: a floating bar over the hero, like Genuka's ── */
    .lp-header { position: sticky; top: 0; z-index: 50; padding-top: 0.75rem; pointer-events: none; }
    .lp-header-bar {
        position: relative; pointer-events: auto; padding-inline: 0.875rem 0.5rem;
        background: hsl(var(--card) / 0.96); border: 1px solid hsl(var(--border));
        border-radius: calc(var(--radius) + 0.375rem);
        box-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 12px 32px -16px rgb(0 0 0 / 0.35);
    }
    /* The section links sit in the middle of the bar, where the eye expects them */
    .lp-nav-links { display: none; }
    @media (min-width: 1100px) {
        .lp-nav-links { display: flex; gap: 0.125rem; position: absolute; left: 50%; transform: translateX(-50%); }
    }
    .lp-nav-link { padding: 0.5rem 0.75rem; border-radius: var(--radius); font-size: 0.875rem; font-weight: 500; color: hsl(var(--muted-foreground)); transition: color 150ms, background-color 150ms; }
    .lp-nav-link:hover { color: hsl(var(--foreground)); background: hsl(var(--muted)); }

    /* ── Hero: a real choir behind the words, the programme of a Sunday beside
       them. The band slides up under the floating bar (its height: 3.5rem bar +
       0.75rem gap), so the photograph starts at the top of the window. ── */
    .lp-hero-band {
        position: relative; isolation: isolate; color: #fff;
        margin-top: -4.25rem; padding-top: 4.25rem; background: #140c06;
    }
    .lp-hero-media { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
    .lp-hero-media > img, .lp-hero-media > video {
        position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 58% 28%;
    }
    .lp-hero-media > video { opacity: 0; transition: opacity 900ms ease; }
    .lp-hero-media > video.is-playing { opacity: 1; }
    /* The veil: heavy where the words are, lighter where the choir is */
    .lp-hero-media::after {
        content: ""; position: absolute; inset: 0;
        background: linear-gradient(90deg, rgb(20 12 6 / 0.88) 0%, rgb(20 12 6 / 0.74) 42%, rgb(20 12 6 / 0.38) 100%);
    }
    @media (max-width: 959px) { .lp-hero-media::after { background: rgb(20 12 6 / 0.74); } }
    .lp-hero { display: grid; gap: 3rem; padding-block: 3.5rem 4.5rem; align-items: center; }
    @media (min-width: 960px) {
        .lp-hero { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 5rem; padding-block: 5.5rem 6.5rem; }
    }
    .lp-hero-text { display: grid; gap: 1.5rem; justify-items: start; }
    .lp-hero-text > .lp-lead { max-width: 36rem; }
    .lp-hero-text > .lp-actions { margin-top: 0.25rem; }
    .lp-hero-band .lp-eyebrow { color: hsl(var(--lp-accent)); }
    .lp-hero-band .lp-display { color: #fff; }
    .lp-hero-band .lp-display mark { color: hsl(var(--lp-accent)); }
    .lp-hero-band .lp-lead { color: rgb(255 255 255 / 0.84); }
    .lp-hero-band .lp-note { color: rgb(255 255 255 / 0.72); }
    .lp-hero-band .lp-second { background: rgb(255 255 255 / 0.1); border-color: rgb(255 255 255 / 0.4); color: #fff; }
    .lp-hero-band .lp-second:hover { background: rgb(255 255 255 / 0.18); }
    .lp-hero-figure { margin: 0; width: 100%; max-width: 30rem; justify-self: center; }
    @media (min-width: 960px) { .lp-hero-figure { justify-self: end; } }
    .lp-hero-caption { margin-top: 1rem; padding-inline: 0.25rem; }

    /* The feuille de messe: numbered, because a programme is a sequence */
    .leaflet {
        border: 1px solid hsl(var(--border)); border-radius: var(--radius); overflow: hidden;
        background: hsl(var(--card));
        box-shadow: 0 1px 2px hsl(var(--foreground) / 0.05), 0 28px 56px -36px hsl(var(--foreground) / 0.35);
    }
    .dark .leaflet { box-shadow: 0 0 0 1px hsl(var(--foreground) / 0.06); }
    .leaflet-head {
        display: flex; align-items: center; gap: 0.875rem;
        padding: 1rem 1.25rem; border-bottom: 1px solid hsl(var(--border));
    }
    .leaflet-choir { display: block; font-size: 0.9375rem; font-weight: 600; color: hsl(var(--foreground)); }
    .leaflet-when { display: block; font-size: 0.8125rem; color: hsl(var(--muted-foreground)); }
    .leaflet-status { margin-left: auto; font-size: 0.75rem; font-weight: 600; color: hsl(var(--lp-accent-text)); }
    .landing-page .date-leaf-month { color: hsl(var(--lp-accent-text)); }
    .leaflet-line { display: grid; grid-template-columns: 1.25rem minmax(0, 1fr); gap: 0.75rem; padding: 0.9375rem 1.25rem; }
    .leaflet-line + .leaflet-line { border-top: 1px solid hsl(var(--border) / 0.7); }
    .leaflet-num { font-size: 0.75rem; font-variant-numeric: tabular-nums; color: hsl(var(--muted-foreground) / 0.8); padding-top: 0.0625rem; }
    .leaflet-cue { display: block; font-size: 0.625rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: hsl(var(--lp-accent-text)); }
    .leaflet-song { display: block; font-family: 'Lora', Georgia, serif; font-style: italic; font-weight: 500; font-size: 1.125rem; line-height: 1.35; color: hsl(var(--foreground)); margin-top: 0.1875rem; }
    .leaflet-meta { display: block; font-size: 0.75rem; color: hsl(var(--muted-foreground)); margin-top: 0.125rem; }

    /* ── What changes: what a choir keeps today, and what it becomes ── */
    .lp-change { border-top: 1px solid hsl(var(--border)); }
    .lp-change-head { display: none; }
    .lp-change-row { display: grid; gap: 0.25rem; padding-block: 1.25rem; border-bottom: 1px solid hsl(var(--border)); }
    .lp-change-before { font-size: 0.875rem; color: hsl(var(--muted-foreground)); }
    .lp-change-after { font-size: 1.0625rem; line-height: 1.55; color: hsl(var(--foreground)); }
    @media (min-width: 760px) {
        .lp-change-head { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 3rem; padding-bottom: 0.875rem; }
        .lp-change { border-top: 0; }
        .lp-change-head + .lp-change-row { border-top: 1px solid hsl(var(--border)); }
        .lp-change-row { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 3rem; padding-block: 1.5rem; align-items: baseline; }
        .lp-change-before { font-size: 1rem; }
        .lp-change-after { font-size: 1.125rem; }
    }

    /* ── Panels: real markup from the app's own vocabulary ── */
    .panel {
        border: 1px solid hsl(var(--border)); border-radius: var(--radius); overflow: hidden;
        background: hsl(var(--card)); box-shadow: 0 1px 2px hsl(var(--foreground) / 0.05);
    }
    .panel-head {
        display: flex; align-items: center; gap: 0.875rem; flex-wrap: wrap;
        padding: 0.875rem 1.25rem; border-bottom: 1px solid hsl(var(--border));
        background: hsl(var(--muted) / 0.45);
    }
    .panel-sub { font-size: 0.8125rem; color: hsl(var(--muted-foreground)); }
    .panel-body { padding: 1.25rem; }
    @media (min-width: 720px) { .panel-body { padding: 1.5rem 1.75rem; } }
    .panel-split { display: grid; }
    @media (min-width: 900px) { .panel-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
    .panel-split > * + * { border-top: 1px solid hsl(var(--border)); }
    @media (min-width: 900px) { .panel-split > * + * { border-top: 0; border-left: 1px solid hsl(var(--border)); } }
    .panel-label { font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: hsl(var(--muted-foreground)); }

    /* Searching the repertoire. An applied filter is ink, not colour. */
    .q-field {
        display: flex; align-items: center; gap: 0.625rem; padding: 0.75rem 0.9375rem;
        border: 1px solid hsl(var(--input)); border-radius: var(--radius);
        background: hsl(var(--background)); font-size: 0.9375rem; color: hsl(var(--muted-foreground));
    }
    .q-chips { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-top: 0.75rem; }
    .q-chip { padding: 0.3125rem 0.6875rem; border-radius: 0.5rem; border: 1px solid hsl(var(--border)); font-size: 0.8125rem; color: hsl(var(--muted-foreground)); }
    .q-chip.is-on { border-color: transparent; background: hsl(var(--lp-accent)); color: hsl(var(--lp-on-accent)); font-weight: 600; }

    /* A song, laid out the way songs/_song lays it out */
    .srow { display: flex; gap: 0.875rem; padding: 0.9375rem 1.25rem; align-items: flex-start; }
    @media (min-width: 720px) { .srow { padding: 0.9375rem 1.75rem; } }
    .srow + .srow { border-top: 1px solid hsl(var(--border) / 0.7); }
    .srow-icon { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: var(--radius); background: hsl(var(--muted)); flex: none; }
    .srow-title { font-size: 1rem; font-weight: 600; color: hsl(var(--foreground)); }
    .srow-badge { margin-left: 0.5rem; font-size: 0.6875rem; font-weight: 500; padding: 0.125rem 0.4375rem; border-radius: 0.375rem; border: 1px solid hsl(var(--border)); color: hsl(var(--muted-foreground)); white-space: nowrap; }
    .srow-meta { display: block; font-size: 0.8125rem; color: hsl(var(--muted-foreground)); margin-top: 0.1875rem; }
    .srow-tags { display: flex; flex-wrap: wrap; gap: 0.3125rem; margin-top: 0.5625rem; }
    .srow-tag { font-size: 0.6875rem; padding: 0.1875rem 0.5rem; border-radius: 0.375rem; background: hsl(var(--muted)); color: hsl(var(--muted-foreground)); }

    /* The pupitres, each its own colour and its real headcount */
    .staff { display: grid; gap: 0.75rem; }
    .staff-row { display: grid; gap: 0.3125rem; }
    .staff-label { display: flex; align-items: baseline; gap: 0.5rem; }
    .staff-name { font-size: 0.75rem; font-weight: 600; }
    .staff-count { font-size: 0.75rem; font-variant-numeric: tabular-nums; color: hsl(var(--muted-foreground)); }
    .staff-track { height: 0.5rem; border-radius: 999px; background: hsl(var(--foreground) / 0.07); }
    .staff-line { display: block; height: 100%; border-radius: 999px; transform-origin: left center; }
    .staff-0 { color: var(--voice-1); } .staff-0 .staff-line { background: var(--voice-1); }
    .staff-1 { color: var(--voice-2); } .staff-1 .staff-line { background: var(--voice-2); }
    .staff-2 { color: var(--voice-3); } .staff-2 .staff-line { background: var(--voice-3); }
    .staff-3 { color: var(--voice-4); } .staff-3 .staff-line { background: var(--voice-4); }
    .staff-4 { color: var(--voice-5); } .staff-4 .staff-line { background: var(--voice-5); }
    .staff-5 { color: var(--voice-6); } .staff-5 .staff-line { background: var(--voice-6); }

    /* The roster beside the balance of the sections */
    .prow { display: flex; align-items: center; gap: 0.75rem; padding: 0.6875rem 0; }
    .prow + .prow { border-top: 1px solid hsl(var(--border) / 0.6); }
    .prow-face { width: 2rem; height: 2rem; border-radius: 999px; background: hsl(var(--muted)); display: grid; place-items: center; font-size: 0.6875rem; font-weight: 700; color: hsl(var(--muted-foreground)); flex: none; }
    .prow-name { font-size: 0.9375rem; color: hsl(var(--foreground)); }
    .prow-role { display: block; font-size: 0.75rem; color: hsl(var(--muted-foreground)); }
    .prow-voices { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.25rem; }
    /* One per voice, high to low. A voice is never shown by colour alone: the
       name is always inside the badge. */
    .spec-voice { font-size: 0.75rem; font-weight: 500; padding: 0.1875rem 0.5625rem; border-radius: 0.375rem; }
    .spec-voice-0 { color: var(--voice-1); background: color-mix(in srgb, var(--voice-1) 13%, transparent); }
    .spec-voice-1 { color: var(--voice-2); background: color-mix(in srgb, var(--voice-2) 13%, transparent); }
    .spec-voice-2 { color: var(--voice-3); background: color-mix(in srgb, var(--voice-3) 13%, transparent); }
    .spec-voice-3 { color: var(--voice-4); background: color-mix(in srgb, var(--voice-4) 15%, transparent); }
    .spec-voice-4 { color: var(--voice-5); background: color-mix(in srgb, var(--voice-5) 15%, transparent); }
    .spec-voice-5 { color: var(--voice-6); background: color-mix(in srgb, var(--voice-6) 13%, transparent); }

    /* A term of Sundays, one row per singer */
    .rollgrid { display: grid; gap: 0.5rem 1.25rem; }
    @media (min-width: 620px) { .rollgrid { grid-template-columns: 10rem minmax(0, 30rem); align-items: center; } }
    .rollgrid-name { font-size: 0.8125rem; color: hsl(var(--foreground)); }
    .rollrow { display: grid; grid-template-columns: repeat(20, minmax(0, 1fr)); gap: 0.25rem; }
    .rollrow > span { aspect-ratio: 1; border-radius: 0.1875rem; }
    .roll-legend { display: flex; flex-wrap: wrap; gap: 0.375rem 1.125rem; }
    .roll-key { display: inline-flex; align-items: center; gap: 0.4375rem; font-size: 0.8125rem; color: hsl(var(--muted-foreground)); }
    .roll-swatch { width: 0.625rem; height: 0.625rem; border-radius: 0.1875rem; }

    /* The file a choir arrives with, and what each of its columns becomes */
    .map-file { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8125rem; color: hsl(var(--foreground)); }
    .mapping-row { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 0.75rem; align-items: center; padding: 0.6875rem 1.125rem; }
    .mapping-row + .mapping-row { border-top: 1px solid hsl(var(--border) / 0.7); }
    .mapping-from { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8125rem; color: hsl(var(--muted-foreground)); }
    .mapping-arrow { font-size: 0.75rem; color: hsl(var(--lp-accent-text)); }
    .mapping-to { font-size: 0.875rem; font-weight: 500; color: hsl(var(--foreground)); text-align: right; }

    /* ── The app itself: the owner's captures behind the app's own navigation ── */
    .shot-frame {
        border: 1px solid hsl(var(--border)); border-radius: var(--radius); overflow: hidden;
        background: hsl(var(--card)); box-shadow: 0 1px 2px hsl(var(--foreground) / 0.05);
    }
    .dark .shot-frame { box-shadow: 0 0 0 1px hsl(var(--foreground) / 0.06); }
    .shot-bar {
        display: flex; align-items: center; gap: 0.75rem;
        padding: 0.5rem 0.625rem; border-bottom: 1px solid hsl(var(--border));
        background: hsl(var(--muted) / 0.5);
    }
    .shot-tabs { display: flex; gap: 0.125rem; overflow-x: auto; scrollbar-width: none; flex: 1 1 auto; }
    .shot-tabs::-webkit-scrollbar { display: none; }
    .shot-tabs > button {
        padding: 0.5rem 1rem; border-radius: 0.5rem; font-size: 0.875rem; font-weight: 500;
        white-space: nowrap; color: hsl(var(--muted-foreground)); border: 1px solid transparent;
        transition: background-color 150ms, color 150ms;
    }
    .shot-tabs > button:hover { color: hsl(var(--foreground)); }
    .shot-tabs > button:focus-visible { outline: 2px solid hsl(var(--foreground)); outline-offset: -2px; }
    .shot-tabs > button[aria-selected="true"] {
        background: hsl(var(--card)); color: hsl(var(--foreground)); font-weight: 600;
        border-color: hsl(var(--border)); box-shadow: 0 1px 2px hsl(var(--foreground) / 0.06);
    }
    .shot-join {
        display: inline-flex; align-items: center; flex: none;
        padding: 0.5rem 1rem; border-radius: 0.5rem;
        border: 1px solid hsl(var(--border)); background: hsl(var(--card));
        font-size: 0.875rem; font-weight: 600; color: hsl(var(--foreground)); white-space: nowrap;
        transition: background-color 150ms;
    }
    .shot-join:hover { background: hsl(var(--muted)); }
    @media (max-width: 720px) { .shot-join { display: none; } }
    /* The desktop captures are unreadable on a phone and heavy on its data, so
       below 640px the tab strip is never shown (its lazy images never load):
       phones get the phone captures instead, or no section at all. */
    .lp-phones { display: none; }
    @media (max-width: 639px) {
        .lp-shots:not(.has-phones), .lp-shots .shot-frame { display: none; }
        .lp-phones {
            display: flex; gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
            margin-inline: -1.25rem; padding: 0.25rem 1.25rem 0.75rem;
        }
        .lp-phones::-webkit-scrollbar { display: none; }
    }
    .lp-phone { flex: 0 0 72%; margin: 0; scroll-snap-align: center; }
    .lp-phone img {
        display: block; width: 100%; height: auto; border-radius: 1.25rem;
        border: 1px solid hsl(var(--border)); background: hsl(var(--card));
        box-shadow: 0 18px 36px -24px rgb(0 0 0 / 0.45);
    }
    .lp-phone figcaption { margin-top: 0.625rem; text-align: center; font-size: 0.8125rem; font-weight: 500; color: hsl(var(--muted-foreground)); }
    /* Whatever a capture's proportions, the frame keeps one shape and shows the
       top of the page, where the interface is. 16:10 captures fit exactly.
       :where() keeps this at zero specificity so a hidden image stays hidden. */
    /* A capture is shown at its own size, never shrunk: shrinking a 1800px
       screen into a ~1100px frame drew the app's text at 60% and resampled it,
       which is what made sharp captures look blurred. Each view is a 16:10
       window onto the top of the capture, centred on the app's content column
       (about 1060 of its 1800 pixels); on a narrower screen the image scales so
       that column still fits, and it is never enlarged past its own size. */
    .shot-frame [data-app-shots-target="shot"] { aspect-ratio: 16 / 10; overflow: hidden; background: #fff; }
    .dark .shot-frame [data-app-shots-target="shot"] { background: #000; }
    .shot-frame :where(img) {
        display: block; position: relative; left: 50%; transform: translateX(-50%);
        width: min(1799px, 170%); max-width: none; height: auto;
    }
    /* The light and dark captures swap on the theme class, not on a media query */
    .shot-dark { display: none; }
    .dark .shot-light { display: none; }
    .dark .shot-dark { display: block; }

    /* ── The languages, set as type on the paper ── */
    .lp-tongues { display: grid; gap: 3.5rem; }
    @media (min-width: 960px) { .lp-tongues { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 5rem; align-items: start; } }
    .incipit { display: block; }
    .incipit + .incipit { margin-top: 1.5rem; }
    .incipit-tongue { display: block; font-size: 0.625rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: hsl(var(--lp-accent-text)); margin-bottom: 0.25rem; }
    .incipit-line { font-family: 'Lora', Georgia, serif; font-style: italic; font-weight: 500; font-size: clamp(1.625rem, 3.6vw, 2.5rem); line-height: 1.15; letter-spacing: -0.015em; color: hsl(var(--foreground)); }
    .tongues { display: flex; flex-wrap: wrap; column-gap: 1.125rem; row-gap: 0.375rem; }
    .tongue { font-size: 1rem; color: hsl(var(--muted-foreground)); }
    .tongue.is-app { color: hsl(var(--foreground)); font-weight: 700; }

    /* ── Questions: one centred column, grouped by theme ── */
    .lp-faq-wrap { max-width: 48rem; margin-inline: auto; display: grid; gap: 2.75rem; }
    .lp-faq-head { display: grid; gap: 0.875rem; text-align: center; justify-items: center; }
    .lp-faq-head > .lp-body { max-width: 34rem; }
    .lp-faq-label { font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: hsl(var(--lp-accent-text)); margin-bottom: 0.5rem; }
    .lp-faq-item { border-bottom: 1px solid hsl(var(--border)); }
    .lp-faq-item > summary {
        display: flex; justify-content: space-between; gap: 1.5rem; align-items: center;
        padding-block: 1rem; cursor: pointer; list-style: none;
        font-size: 1rem; font-weight: 600; color: hsl(var(--foreground));
    }
    .lp-faq-item > summary::-webkit-details-marker { display: none; }
    /* A chevron that turns when the row is open */
    .lp-faq-item > summary::after {
        content: ""; flex: none; width: 0.5rem; height: 0.5rem; margin-right: 0.25rem;
        border: solid hsl(var(--muted-foreground)); border-width: 0 1.5px 1.5px 0;
        transform: translateY(-25%) rotate(45deg); transition: transform 200ms;
    }
    .lp-faq-item[open] > summary::after { transform: translateY(25%) rotate(-135deg); }
    .lp-faq-item > p { padding-bottom: 1.125rem; font-size: 0.9375rem; line-height: 1.65; color: hsl(var(--muted-foreground)); }
    .lp-faq-more {
        display: grid; gap: 0.5rem; justify-items: center; text-align: center;
        padding: 2rem 1.5rem; border-radius: var(--radius); background: hsl(var(--lp-tint));
        border: 1px solid hsl(var(--lp-accent) / 0.18);
    }
    .lp-faq-more-title { font-size: 1.125rem; font-weight: 700; color: hsl(var(--foreground)); }
    .lp-faq-more > .lp-cta { margin-top: 0.75rem; }

    /* ── Closing: the page's one full band of colour ── */
    .lp-closing { background: hsl(var(--lp-accent)); color: hsl(var(--lp-on-accent)); }
    .lp-closing-inner { display: grid; justify-items: center; gap: 1.25rem; text-align: center; padding-block: 5rem; }
    @media (min-width: 900px) { .lp-closing-inner { padding-block: 7rem; } }
    .lp-closing .lp-display { max-width: 44rem; color: hsl(var(--lp-on-accent)); }
    .lp-closing .lp-lead { max-width: 34rem; color: hsl(var(--lp-on-accent) / 0.8); }
    .lp-closing .lp-actions { justify-content: center; margin-top: 0.5rem; }

    /* ── Real choirs: a bento of photographs, each with its place in a caption ── */
    .lp-gallery { display: grid; gap: 0.75rem; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 10rem; }
    @media (min-width: 900px) { .lp-gallery { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: 15rem; gap: 1rem; } }
    .lp-photo { position: relative; margin: 0; overflow: hidden; border-radius: var(--radius); background: hsl(var(--muted)); }
    .lp-photo.is-wide { grid-column: span 2; grid-row: span 2; }
    .lp-photo.is-tall { grid-row: span 2; }
    .lp-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
    .lp-photo figcaption {
        position: absolute; left: 0.625rem; bottom: 0.625rem; max-width: calc(100% - 1.25rem);
        padding: 0.3125rem 0.625rem; border-radius: 0.375rem; background: rgb(20 12 6 / 0.74);
        color: #fff; font-size: 0.75rem; font-weight: 500; line-height: 1.35;
    }

    /* ── The languages, over a photograph of a choir: the one band where type sits
       on an image, under a flat veil heavy enough to read against ── */
    .lp-invert { position: relative; isolation: isolate; background: #140c06; color: #fff; overflow: hidden; }
    .lp-invert > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
    .lp-invert::before { content: ""; position: absolute; inset: 0; z-index: -1; background: rgb(20 12 6 / 0.8); }
    .lp-invert .lp-head, .lp-invert .incipit-line { color: #fff; }
    .lp-invert .lp-eyebrow, .lp-invert .incipit-tongue { color: hsl(var(--lp-accent)); }
    .lp-invert .lp-note { color: rgb(255 255 255 / 0.7); }
    .lp-invert .tongue { color: rgb(255 255 255 / 0.66); }
    .lp-invert .tongue.is-app { color: #fff; }

    /* ── Footer: dark, one line ── */
    .lp-footer { background: hsl(var(--lp-deep)); color: #fff; }
    .lp-footer-name { font-size: 0.9375rem; font-weight: 700; }
    .lp-footer .lp-note { color: rgb(255 255 255 / 0.6); }
    .lp-foot-link { font-size: 0.9375rem; color: rgb(255 255 255 / 0.7); transition: color 150ms; }
    .lp-foot-link:hover { color: #fff; }
    .lp-credits > summary { cursor: pointer; list-style: none; font-size: 0.75rem; color: rgb(255 255 255 / 0.55); }
    .lp-credits > summary::-webkit-details-marker { display: none; }
    .lp-credits > summary:hover { color: #fff; }
    .lp-credits ul { display: grid; gap: 0.25rem; margin-top: 0.5rem; font-size: 0.75rem; line-height: 1.5; color: rgb(255 255 255 / 0.6); }
    .lp-credits a { text-decoration: underline; text-underline-offset: 2px; }
    .lp-credits a:hover { color: #fff; }

    /* On the landing the plan switch's chosen period is orange too */
    .landing-page .plan-switch { background: hsl(var(--card)); border: 1px solid hsl(var(--border)); }
    .landing-page .plan-switch > button[aria-current="page"] { background: hsl(var(--lp-accent)); color: hsl(var(--lp-on-accent)); }

    /* One orchestrated moment and one echo: the programme writes itself line by
       line when the page opens, and the six pupitres grow like a canon. */
    @media (prefers-reduced-motion: no-preference) {
        .reveal { opacity: 0; transform: translateY(16px); transition: opacity 700ms cubic-bezier(0.16, 1, 0.3, 1), transform 700ms cubic-bezier(0.16, 1, 0.3, 1); }
        .reveal.is-in { opacity: 1; transform: none; }
        .leaflet-line { opacity: 0; transform: translateY(6px); }
        .is-in .leaflet-line { animation: line-in 600ms cubic-bezier(0.16, 1, 0.3, 1) forwards; animation-delay: calc(250ms + var(--i) * 140ms); }
        @keyframes line-in { to { opacity: 1; transform: none; } }
        .lp-photo img { transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1); }
        .lp-photo:hover img { transform: scale(1.04); }
        .staff-line { transform: scaleX(0); }
        .is-in .staff-line { animation: staff-in 900ms cubic-bezier(0.16, 1, 0.3, 1) forwards; animation-delay: calc(var(--i) * 110ms); }
        @keyframes staff-in { to { transform: none; } }
    }
}
