/*
 * Baseline styling. Mobile-first (the app is used phone-in-hand on the go).
 * Sober, high-contrast, large tap targets. Hooks onto the existing BEM classes;
 * only class selectors (plus a minimal element reset/base, the allowed exception).
 *
 * Theming: the whole palette lives in custom properties on :root, swapped once in
 * the prefers-color-scheme:dark block at the bottom — every rule reads var(), so a
 * single override theme-switches the app without duplicating any selector.
 */

/* NOTE: no cross-document @view-transition here — it was tried for the sync
   reloads and ROLLED BACK: a navigation interrupted by connectivity loss can
   leave the transition's snapshot overlay stuck, freezing all interaction.
   Remote changes soft-swap the DOM without navigating, so it's moot. */

/* --- Palette (light, default) --- */
:root {
    color-scheme: light dark;

    --bg: #f7f8f9;
    --surface: #ffffff;
    --text: #15171a;
    --text-soft: #3a3f45;
    --text-muted: #6a7178;
    --text-faint: #9aa0a6;

    --border: #e2e5e8;
    --border-subtle: #eef0f2;

    --accent: #1e5c4a;
    --accent-hover: #184b3d;
    --accent-soft-bg: #ecf3f0;
    --on-accent: #ffffff;

    --neutral-bg: #eef0f2;
    --neutral-bg-hover: #e2e5e8;
    --hover-bg: #f2f4f5;

    --danger: #a33a3a;
    --danger-bg: #fbeded;
    --error-text: #8a2c2c;
    --error-bg: #fbeded;

    --drag-handle: #bfc4c9;

    /* Curated "Quiet" list tints — muted mid-tone hues. Only the pure hue is set;
       the column mixes it with --surface, so each tint adapts to light/dark on its
       own (no second palette needed for the dark theme). */
    --hue-sage: #5f8a6e;
    --hue-slate: #6b7f99;
    --hue-clay: #a9745c;
    --hue-sand: #ad9a64;
    --hue-mauve: #8c7498;
    --hue-rose: #ab7385;
    --hue-teal: #4f8a89;
    --hue-amber: #bf8a40;

    --shadow-sm: 0 1px 2px rgba(20, 23, 26, 0.06);
    --shadow-md: 0 6px 20px rgba(20, 23, 26, 0.10);

    --radius: 0.5rem;
    --radius-sm: 0.375rem;
    --transition: 0.15s ease;
}

/* --- Reset / base --- */
*,
*::before,
*::after {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text);
    background-color: var(--bg);
}

button {
    font: inherit;
    cursor: pointer;
    transition: background-color var(--transition), border-color var(--transition), color var(--transition);
}

input {
    font: inherit;
    color: var(--text);
    transition: background-color var(--transition), border-color var(--transition);
}

/* --- Login --- */
.login {
    max-width: 22rem;
    margin: 4rem auto;
    padding: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    background-color: var(--surface);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-sm);
}

.login__title {
    margin: 0 0 0.5rem;
    font-size: 1.25rem;
}

.login__error {
    margin: 0;
    padding: 0.625rem 0.75rem;
    border-radius: var(--radius);
    color: var(--error-text);
    background-color: var(--error-bg);
}

.login__label {
    font-size: 0.875rem;
    font-weight: 600;
}

.login__input {
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
}

.login__input:focus {
    outline: 2px solid var(--accent);
    border-color: transparent;
}

.login__remember {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    font-size: 0.875rem;
    color: var(--text-muted);
}

.login__submit {
    margin-top: 0.75rem;
    padding: 0.7rem;
    border: none;
    border-radius: var(--radius);
    font-weight: 600;
    color: var(--on-accent);
    background-color: var(--accent);
}

.login__submit:hover {
    background-color: var(--accent-hover);
}

/* --- Empty states --- */
.home-empty,
.board__empty {
    max-width: 32rem;
    margin: 3rem auto;
    padding: 0 1rem;
    text-align: center;
    color: var(--text-muted);
}

/* --- Board shell --- */
/* Full-width on purpose: the header spans the top and the list columns below
   scroll horizontally across the viewport (Trello-style board). Flex column over
   the full viewport height so the columns region can fill all remaining space. */
.board {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 1rem 1rem 2rem;
}

.board__flash {
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: var(--radius);
    color: var(--error-text);
    background-color: var(--error-bg);
}

.board__notice {
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: var(--radius);
    color: var(--accent-hover);
    background-color: var(--accent-soft-bg);
    /* The invite URL is long and unbreakable — let it wrap inside the banner. */
    overflow-wrap: anywhere;
}

.board__header {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 0.75rem;
}

.board__title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    padding: 0.4rem 0.5rem;
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text);
    border: 1px solid transparent;
    border-radius: var(--radius);
    background-color: transparent;
}

.board__title:hover {
    border-color: var(--border-subtle);
}

.board__title:focus {
    outline: 2px solid var(--accent);
    border-color: transparent;
    background-color: var(--surface);
}

/* --- Disclosure menu (board burger / current-list gear) --- */
.menu {
    position: relative;
    flex: 0 0 auto;
}

.menu__trigger {
    padding: 0.4rem 0.6rem;
    font-size: 1.1rem;
    color: var(--text-soft);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: transparent;
}

.menu__trigger:hover {
    background-color: var(--neutral-bg);
}

.menu__panel {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 10;
    min-width: 14rem;
    padding: 0.35rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
    box-shadow: var(--shadow-md);
}

.menu__heading {
    margin: 0.25rem 0.25rem 0.35rem;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-faint);
}

.menu__list {
    margin: 0 0 0.5rem;
    padding: 0;
    list-style: none;
}

.menu__item {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.menu__switch {
    /* Board name takes the row; the delete cross keeps its intrinsic width. */
    flex: 1 1 auto;
    min-width: 0;
}

.menu__delete-btn {
    flex: 0 0 auto;
    padding: 0.35rem 0.55rem;
    font-size: 1.1rem;
    line-height: 1;
    color: var(--danger);
    border: none;
    border-radius: var(--radius-sm);
    background-color: transparent;
    cursor: pointer;
    transition: background-color var(--transition);
}

.menu__delete-btn:hover {
    background-color: var(--danger-bg);
}

.menu__option {
    display: block;
    width: 100%;
    padding: 0.5rem 0.75rem;
    text-align: left;
    color: var(--text);
    /* Some options are <a> (board switch, members, admin): drop the underline
     * so they read like the <button> options, per the "Quiet" design. */
    text-decoration: none;
    border: none;
    border-radius: var(--radius-sm);
    background-color: transparent;
}

.menu__option:hover {
    background-color: var(--hover-bg);
}

.menu__option.is-active {
    font-weight: 600;
    color: var(--accent);
    background-color: var(--accent-soft-bg);
}

/* Version line at the bottom of the burger menu: informational only, styled as
   a faint footnote behind a separator so it never reads as an action. */
.menu__version {
    margin: 0.35rem 0.25rem 0.1rem;
    padding-top: 0.45rem;
    border-top: 1px solid var(--border);
    font-size: 0.75rem;
    color: var(--text-faint);
}

.menu__member {
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.4rem 0.75rem;
}

.menu__member-name {
    min-width: 0;
    overflow-wrap: anywhere;
}

.menu__member-role {
    flex: 0 0 auto;
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* --- Board of list columns (Trello-style) --- */
/* The columns sit in a horizontal row that scrolls sideways to reach further
   lists; the page itself still scrolls vertically for a tall column. align-items
   keeps columns top-aligned and each as tall as its own content. */
.board-lists {
    /* Fill the height left under the header so the horizontal scroll can be grabbed
       anywhere down to the bottom of the screen — on a phone you needn't reach back
       up to a short column to swipe sideways. NOTE: this region never scrolls
       vertically in practice — .board has min-height (not height), so a tall column
       grows the page and the WINDOW is the vertical scroller (the soft swap
       preserves that window scroll explicitly, sync_controller). */
    flex: 1 1 auto;
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    overflow-x: auto;
    /* Breathing room so a column's focus outline isn't clipped at the edges. */
    padding: 0.25rem 0.1rem 0.75rem;
}

.list-column {
    flex: 0 0 18rem;
    /* Without this a column can never get narrower than its widest row (flex
       min-width:auto), silently overriding flex-basis — on a small screen the
       column then sticks out past the right edge. Inner rows wrap/shrink. */
    min-width: 0;
    display: flex;
    flex-direction: column;
    padding: 0.85rem;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius);
    /* Tint is driven by --list-hue (default = surface, i.e. no tint). The
       data-list-color attribute overrides --list-hue; the column gets a soft fill
       and items a lighter one (smaller mix), both from the same hue + theme surface.
       The attribute (not a class) carries the colour so the JS sets state without
       touching BEM classes. */
    --list-hue: var(--surface);
    --list-tint: color-mix(in srgb, var(--list-hue) 26%, var(--surface));
    --list-item-tint: color-mix(in srgb, var(--list-hue) 13%, var(--surface));
    background-color: var(--list-tint);
}

/* On a phone the fixed 18rem column left a wide strip of the neighbour showing — wide
   enough that its item grab handles fell under the thumb, so a sideways swipe sometimes
   started an item drag instead. Make each column fill the whole scroller: one list per
   screen, the neighbour stays fully offscreen. Desktop keeps 18rem so several columns
   stay visible at once. */
@media (max-width: 40rem) {
    /* Swipe pages one full-width column at a time and settles on it, so a list
       (or the add-list column) is always pinned to the left rather than left
       mid-scroll. Safe again now that cross-list item drag was removed — it no
       longer needs the board to autoscroll sideways, which is what this snap
       used to fight. `stop: always` forces a pause on every column even on a
       fast fling. */
    .board-lists {
        scroll-snap-type: x mandatory;
    }

    .list-column {
        /* Sized against the scroller itself, NOT the viewport (was 90vw): Chrome
           Android's font-size accessibility setting scales rem-based paddings but
           not vw, so a vw column outgrew the scroller and its right edge was cut
           off. A percentage tracks the real available width whatever the zoom. */
        flex-basis: 100%;
        scroll-snap-align: start;
        scroll-snap-stop: always;
    }
}

.list-column[data-list-color="sage"] { --list-hue: var(--hue-sage); }
.list-column[data-list-color="slate"] { --list-hue: var(--hue-slate); }
.list-column[data-list-color="clay"] { --list-hue: var(--hue-clay); }
.list-column[data-list-color="sand"] { --list-hue: var(--hue-sand); }
.list-column[data-list-color="mauve"] { --list-hue: var(--hue-mauve); }
.list-column[data-list-color="rose"] { --list-hue: var(--hue-rose); }
.list-column[data-list-color="teal"] { --list-hue: var(--hue-teal); }
.list-column[data-list-color="amber"] { --list-hue: var(--hue-amber); }

/* --- Colour palette (list gear menu) --- */
.swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    padding: 0.25rem;
    margin-bottom: 0.25rem;
}

.swatch {
    width: 1.5rem;
    height: 1.5rem;
    border: 1px solid var(--border);
    border-radius: 50%;
    background-color: var(--swatch-hue, var(--surface));
}

.swatch:hover {
    border-color: var(--text-muted);
}

/* The list's current colour. Ringed with a surface-coloured gap so the mark
   reads on every hue, light and dark, instead of fighting the fill. */
.swatch[aria-pressed="true"] {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--accent);
}

.swatch--sage { --swatch-hue: var(--hue-sage); }
.swatch--slate { --swatch-hue: var(--hue-slate); }
.swatch--clay { --swatch-hue: var(--hue-clay); }
.swatch--sand { --swatch-hue: var(--hue-sand); }
.swatch--mauve { --swatch-hue: var(--hue-mauve); }
.swatch--rose { --swatch-hue: var(--hue-rose); }
.swatch--teal { --swatch-hue: var(--hue-teal); }
.swatch--amber { --swatch-hue: var(--hue-amber); }

/* "No colour": a surface circle crossed by a thin diagonal. */
.swatch--reset {
    background-image: linear-gradient(
        to top right,
        transparent calc(50% - 1px), var(--text-faint) calc(50% - 1px),
        var(--text-faint) calc(50% + 1px), transparent calc(50% + 1px)
    );
}

/* Trailing "add a list" column: a quiet dashed placeholder, no card fill. */
.list-column--add {
    background-color: transparent;
    border-style: dashed;
}

.list-column__header {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 0.5rem;
}

.list-column__title {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.4rem 0.5rem;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--text);
    border: 1px solid transparent;
    border-radius: var(--radius);
    background-color: transparent;
}

.list-column__title:hover {
    border-color: var(--border-subtle);
}

.list-column__title:focus {
    outline: 2px solid var(--accent);
    border-color: transparent;
    background-color: var(--bg);
}

/* --- Inline add forms (add-list, new-board) — same shape, two blocks --- */
.list-form,
.board-form {
    display: flex;
    gap: 0.5rem;
}

.board-form {
    margin-bottom: 0.75rem;
}

.list-form__input,
.board-form__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
}

.list-form__input:focus,
.board-form__input:focus {
    outline: 2px solid var(--accent);
    border-color: transparent;
}

.list-form__submit,
.board-form__submit {
    flex: 0 0 auto;
    padding: 0.6rem 1rem;
    border: none;
    border-radius: var(--radius);
    font-weight: 600;
    color: var(--on-accent);
    background-color: var(--accent);
}

.list-form__submit:hover,
.board-form__submit:hover {
    background-color: var(--accent-hover);
}

/* Inline validation message for the add-list / new-board fields. Plain italic
   red text (not the pill the checklist add-field uses) — errors are always red. */
.list-form__error,
.board-form__error {
    margin: 0.35rem 0 0;
    color: var(--error-text);
    font-size: 0.8rem;
    font-style: italic;
}

/* Stacked variant for the narrow "add a list" column: field over a full-width
   button instead of side by side. */
.list-form--stacked {
    flex-direction: column;
}

.list-delete__submit {
    display: block;
    width: 100%;
    padding: 0.5rem 0.75rem;
    text-align: left;
    color: var(--danger);
    border: none;
    border-radius: var(--radius-sm);
    background-color: transparent;
}

.list-delete__submit:hover {
    background-color: var(--danger-bg);
}

/* --- Checklist --- */
.checklist__add-area {
    position: relative;
    margin-top: 0.75rem;
}

.checklist__add {
    width: 100%;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
}

.checklist__add:focus {
    outline: 2px solid var(--accent);
    border-color: transparent;
}

.checklist__error {
    margin: 0.5rem 0 0;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius);
    color: var(--error-text);
    background-color: var(--error-bg);
}

/* Floats just below the add field. */
.autocomplete {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 10;
    margin: 0;
    padding: 0.25rem;
    list-style: none;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
    box-shadow: var(--shadow-md);
}

.autocomplete__option {
    display: block;
    width: 100%;
    padding: 0.5rem 0.75rem;
    text-align: left;
    color: var(--text);
    border: none;
    border-radius: var(--radius-sm);
    background-color: transparent;
}

.autocomplete__option:hover {
    background-color: var(--hover-bg);
}

.checklist__items,
.checked__items {
    margin: 0;
    padding: 0;
    list-style: none;
}

.checklist__item {
    display: flex;
    gap: 0.25rem;
    align-items: center;
    padding: 0.35rem 0.25rem;
    border-bottom: 1px solid var(--border-subtle);
    /* Lighter shade of the list's tint (surface when the list has no colour). */
    background-color: var(--list-item-tint);
    transition: background-color var(--transition);
}

.checklist__item:hover {
    background-color: var(--hover-bg);
}

.checklist__drag {
    flex: 0 0 auto;
    padding: 0.25rem;
    color: var(--drag-handle);
    border: none;
    background-color: transparent;
    cursor: grab;
}

.checklist__check {
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    accent-color: var(--accent);
}

.checklist__label {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.5rem;
    color: var(--text);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background-color: transparent;
    /* Textarea reset: match the surrounding text, grow via JS (checklist#autogrow)
       instead of scrolling, and wrap long unbroken strings instead of overflowing. */
    display: block;
    font: inherit;
    line-height: 1.4;
    resize: none;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.checklist__label:focus {
    outline: 2px solid var(--accent);
    border-color: transparent;
    background-color: var(--bg);
}

.checklist__label.is-checked {
    color: var(--text-faint);
    text-decoration: line-through;
    text-decoration-color: var(--border);
    text-decoration-thickness: 1px;
}

.checklist__move {
    flex: 0 0 auto;
    padding: 0.25rem 0.5rem;
    color: var(--text-muted);
    border: none;
    border-radius: var(--radius-sm);
    background-color: transparent;
}

.checklist__move:hover {
    background-color: var(--hover-bg);
}

/* Drag placeholder shared by items and tabs (SortableJS ghostClass). */
.is-dragging {
    opacity: 0.4;
}

/* --- Checked section --- */
.checked {
    margin-top: 1.25rem;
}

.checked__summary {
    padding: 0.5rem 0;
    cursor: pointer;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.checked__clear-btn {
    margin-top: 0.5rem;
    padding: 0.4rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text-soft);
    background-color: transparent;
}

.checked__clear-btn:hover {
    background-color: var(--neutral-bg);
}

/* --- Move-to-list menu (floated under the trigger via fixed positioning) --- */
.move-menu {
    position: fixed;
    z-index: 10;
    min-width: 10rem;
    margin: 0;
    padding: 0.35rem;
    list-style: none;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
    box-shadow: var(--shadow-md);
}

.move-menu__option {
    display: block;
    width: 100%;
    padding: 0.5rem 0.75rem;
    text-align: left;
    color: var(--text);
    border: none;
    border-radius: var(--radius-sm);
    background-color: transparent;
}

.move-menu__option:hover {
    background-color: var(--hover-bg);
}

/*
 * Dark theme — follows the device setting (no in-app toggle). Only the palette
 * variables change; every rule above reads them, so nothing else is restated.
 * The pine accent is brightened to keep contrast on the dark surfaces; the
 * danger and error tints become muted backgrounds with light text.
 */
@media (prefers-color-scheme: dark) {
    :root {
        --bg: #15171a;
        --surface: #1d2024;
        --text: #e6e8ea;
        --text-soft: #c2c7cc;
        --text-muted: #969ca2;
        --text-faint: #6e747a;

        --border: #33373c;
        --border-subtle: #26292d;

        --accent: #4fae8e;
        --accent-hover: #5cbd9c;
        --accent-soft-bg: #16241e;
        --on-accent: #0c130f;

        --neutral-bg: #26292d;
        --neutral-bg-hover: #2f3338;
        --hover-bg: #23262a;

        --danger: #ef9a9a;
        --danger-bg: #371f1f;
        --error-text: #f0b4b4;
        --error-bg: #371f1f;

        --drag-handle: #565b61;

        --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.45);
        --shadow-md: 0 6px 22px rgba(0, 0, 0, 0.55);
    }
}

/* --- Sync refresh banner --- */
.sync-banner {
    position: fixed;
    left: 50%;
    top: 1rem;
    transform: translateX(-50%);
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    max-width: calc(100% - 2rem);
    padding: 0.625rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    background-color: var(--surface);
    box-shadow: var(--shadow-md);
}

/* display:flex above outranks the [hidden] UA rule, so the banner would stay
   visible (empty) once re-hidden — restore the hide. */
.sync-banner[hidden] {
    display: none;
}

.sync-banner__text {
    color: var(--text-soft);
}

.sync-banner__refresh {
    padding: 0.375rem 0.75rem;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--on-accent);
    background-color: var(--accent);
    cursor: pointer;
    transition: background-color var(--transition);
}

.sync-banner__refresh:hover {
    background-color: var(--accent-hover);
}

/* While the refresh banner is up the board is stale: the lists are made `inert`
   (blocks mouse AND keyboard, so no edit can land on a board the user can't yet
   see the latest state of) and dimmed until they reload. The header/menu stay
   live so they can still switch board or hit Refresh. */
.board-lists[inert] {
    opacity: 0.55;
}

/* --- Offline indicator --- */
/* Fixed overlay ("Quiet" pill): showing/hiding it never shifts the layout. At
   the bottom so it cannot collide with the sync banner pinned to the top. */
.offline-pill {
    position: fixed;
    bottom: 0.75rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    max-width: calc(100% - 2rem);
    margin: 0;
    padding: 0.6rem 1.3rem;
    font-size: 1rem;
    white-space: nowrap;
    color: var(--text-faint);
    border: 1px solid var(--border);
    border-radius: 999px;
    background-color: var(--surface);
    box-shadow: var(--shadow-sm);
}

/* --- Boot splash --- */
/* Full-viewport cover shown from the first paint: the scroll restore and the
   offline replay settle the board underneath, then the splash fades away.
   pointer-events dies with the fade (is-hidden) so the fading cover can
   never swallow a tap meant for the board. */
.splash {
    position: fixed;
    inset: 0;
    /* The only tier above the app's shared 10 (pill, banner, menus): the
       splash alone must cover the entire page, overlays included. */
    z-index: 100;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    align-items: center;
    justify-content: center;
    background-color: var(--bg);
    transition: opacity 250ms ease;
}

/* The display:flex above would override the UA's [hidden] rule (same trap as
   .sync-banner[hidden]): restate it or the lifted splash stays in layout and
   in the accessibility tree forever. */
.splash[hidden] {
    display: none;
}

.splash.is-hidden {
    pointer-events: none;
    opacity: 0;
}

/* The branding fades in slightly late: a skipped splash (reload within the
   same session of use) is hidden by the controller before this delay ends, so
   the user only ever sees the cover's page-coloured background — nothing. */
.splash__icon,
.splash__wordmark,
.splash__version {
    animation: splash-appear 250ms ease 200ms backwards;
}

@keyframes splash-appear {
    from {
        opacity: 0;
    }
}

.splash__icon {
    width: 4.5rem;
    height: 4.5rem;
    margin-bottom: 0.5rem;
    /* Launcher-tile look: svg overflow:hidden (default) lets the radius clip
       the icon's square background. */
    border-radius: 22%;
}

.splash__wordmark {
    margin: 0;
    font-size: 2.25rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    /* The icon carries the brand colour; a second green here would clash. */
    color: var(--text);
}

.splash__version {
    margin: 0;
    font-size: 0.85rem;
    color: var(--text-faint);
}

@media (prefers-reduced-motion: reduce) {
    .splash {
        transition: none;
    }

    .splash__icon,
    .splash__wordmark,
    .splash__version {
        animation: none;
    }
}

/* --- Members & invitations page --- */
.members {
    max-width: 32rem;
    margin: 0 auto;
    padding: 1rem;
}

.members__header {
    display: flex;
    gap: 0.75rem;
    align-items: baseline;
    margin-bottom: 1rem;
}

.members__back {
    flex: 0 0 auto;
    color: var(--text-muted);
    text-decoration: none;
}

.members__title {
    margin: 0;
    font-size: 1.5rem;
    overflow-wrap: anywhere;
}

.members__subtitle {
    margin: 0 0 0.5rem;
    font-size: 1rem;
}

.members__list {
    margin: 0 0 1.25rem;
    padding: 0;
    list-style: none;
}

.members__item {
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.5rem 0.25rem;
    border-bottom: 1px solid var(--border-subtle);
}

.members__name {
    min-width: 0;
    overflow-wrap: anywhere;
}

.members__role {
    flex: 0 0 auto;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.members__invite-btn {
    padding: 0.6rem 1rem;
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius);
    background-color: var(--accent);
    cursor: pointer;
    transition: background-color var(--transition);
}

.members__invite-btn:hover {
    background-color: var(--accent-hover);
}

.invite-link {
    margin-bottom: 1.25rem;
    padding: 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--accent-soft-bg);
}

.invite-link__label {
    margin: 0 0 0.5rem;
    font-size: 0.85rem;
    color: var(--text-soft);
}

.invite-link__row {
    display: flex;
    gap: 0.5rem;
}

.invite-link__url {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background-color: var(--surface);
    color: var(--text);
}

.invite-link__copy {
    flex: 0 0 auto;
    padding: 0.5rem 0.9rem;
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius-sm);
    background-color: var(--accent);
    cursor: pointer;
    transition: background-color var(--transition);
}

.invite-link__copy:hover {
    background-color: var(--accent-hover);
}

/* --- Admin: manage users --- */
.admin {
    max-width: 36rem;
    margin: 0 auto;
    padding: 1rem;
}

.admin__back {
    display: inline-block;
    margin-bottom: 0.75rem;
    color: var(--text-muted);
    text-decoration: none;
}

.admin__title {
    margin: 0 0 1rem;
    font-size: 1.5rem;
    overflow-wrap: anywhere;
}

.admin__flash {
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: var(--radius);
    color: var(--error-text);
    background-color: var(--error-bg);
}

.admin__notice {
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: var(--radius);
    color: var(--accent-hover);
    background-color: var(--accent-soft-bg);
}

.admin__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.admin__row {
    display: flex;
    gap: 0.75rem;
    justify-content: space-between;
    align-items: center;
    padding: 0.6rem 0.25rem;
    border-bottom: 1px solid var(--border-subtle);
}

.admin__identity {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: baseline;
    min-width: 0;
}

.admin__name {
    font-weight: 600;
    overflow-wrap: anywhere;
}

.admin__email {
    color: var(--text-soft);
    font-size: 0.85rem;
    overflow-wrap: anywhere;
}

.admin__date {
    color: var(--text-faint);
    font-size: 0.75rem;
}

.admin__badge {
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-sm);
    background-color: var(--neutral-bg);
    color: var(--text-soft);
    font-size: 0.7rem;
}

.admin__action {
    flex: 0 0 auto;
    color: var(--danger);
    text-decoration: none;
}

.admin__self {
    flex: 0 0 auto;
    color: var(--text-faint);
    font-size: 0.85rem;
}

.admin__notice-text {
    margin: 0.75rem 0 0.4rem;
    color: var(--text-soft);
}

.admin__board-list {
    margin: 0 0 0.75rem;
    padding-left: 1.25rem;
}

.admin__select {
    display: block;
    width: 100%;
    margin-bottom: 0.75rem;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background-color: var(--surface);
    color: var(--text);
}

.admin__delete-btn {
    padding: 0.6rem 1rem;
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius);
    background-color: var(--danger);
    cursor: pointer;
}
