/* Brännbole - hand-written, mobile first.
 *
 * Six screens do not need a framework, and on a phone out by the dock the payload is the thing
 * the member actually waits for. Everything below is built from one token layer, so the whole
 * app can be re-tuned from the top of this file.
 *
 * On type: no webfont. A request to a font CDN on every page load is a dependency and a privacy
 * leak for a twenty-member association, and it costs a flash of unstyled text on the mobile
 * connection these pages are read on. The system stack is tuned instead - a real scale, tighter
 * headings, tabular numerals - which is most of what a typeface was going to buy.
 */

:root {
    /* --- palette ---------------------------------------------------------
     * Warm neutrals rather than blue-grey: this is a list about gravel, docks and hedges, and
     * warm greys sit better next to photographs of them.
     */
    --bg: #f6f6f4;
    --surface: #ffffff;
    --surface-sunken: #f1f1ee;
    --border: #e5e4df;
    --border-strong: #d4d3cc;
    --text: #1a1d1b;
    --text-soft: #434945;
    --muted: #6b7069;

    --accent: #2c6a4a;
    --accent-hover: #235540;
    --accent-soft: #edf4f0;
    --link: #235540;

    --red: #a8291f;
    --red-soft: #fbeceb;

    /* Filled controls carry their own pair. --accent is also a text colour, and a text colour
       has to lighten in dark mode - which would leave white labels on a pale green. */
    --btn-bg: #2c6a4a;
    --btn-bg-hover: #235540;
    --btn-fg: #ffffff;

    --topbar-bg: #22553c;
    --topbar-fg: #ffffff;
    --topbar-fg-dim: rgba(255, 255, 255, .78);
    --topbar-active: rgba(255, 255, 255, .15);

    --focus-ring: rgba(44, 106, 74, .28);

    /* --- elevation -------------------------------------------------------
     * Two soft layers rather than one hard one: a tight contact shadow plus a wide, faint
     * ambient one is what stops a card looking like a box with a grey line under it.
     */
    --shadow-sm: 0 1px 2px rgba(22, 28, 24, .05);
    --shadow-md: 0 1px 2px rgba(22, 28, 24, .04), 0 6px 16px -8px rgba(22, 28, 24, .14);
    --shadow-lg: 0 2px 4px rgba(22, 28, 24, .05), 0 14px 32px -12px rgba(22, 28, 24, .20);

    /* --- geometry --------------------------------------------------------- */
    --r-sm: 8px;
    --r-md: 12px;
    --r-lg: 16px;
    --r-pill: 999px;

    --s-1: 4px;
    --s-2: 8px;
    --s-3: 12px;
    --s-4: 16px;
    --s-5: 24px;
    --s-6: 32px;
    --s-7: 48px;

    /* Minimum comfortable tap target. */
    --tap: 44px;

    --ease: cubic-bezier(.2, .7, .3, 1);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #131614;
        --surface: #1b1f1d;
        --surface-sunken: #171b19;
        --border: #2b302d;
        --border-strong: #3a413d;
        --text: #e8ebe8;
        --text-soft: #c3c9c5;
        --muted: #99a29c;

        --accent: #6dbc93;
        --accent-hover: #86cba6;
        --accent-soft: #1d2a23;
        --link: #86cba6;

        --red: #ef9a93;
        --red-soft: #2d1e1d;

        --btn-bg: #2f7350;
        --btn-bg-hover: #3a8a61;
        --btn-fg: #ffffff;

        --topbar-bg: #161d19;
        --topbar-fg: #e8ebe8;
        --topbar-fg-dim: #9aa8a0;
        --topbar-active: rgba(255, 255, 255, .09);

        --focus-ring: rgba(109, 188, 147, .32);

        /* Shadows do not read on a dark background; the borders carry the separation instead. */
        --shadow-sm: none;
        --shadow-md: none;
        --shadow-lg: 0 16px 40px -16px rgba(0, 0, 0, .7);
    }
}

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    margin: 0;
    /* 17px: this is read outdoors, in daylight, by people who are not twenty. */
    font: 400 17px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI",
          Roboto, "Helvetica Neue", Arial, sans-serif;
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-synthesis-weight: none;
}

::selection { background: var(--accent); color: #fff; }

/* --- type scale ---------------------------------------------------------- */

h1, h2, h3 {
    /* Negative tracking on large text: the default spacing is set for body copy and looks
       slack once the glyphs get big. */
    letter-spacing: -.018em;
    color: var(--text);
    text-wrap: balance;
}

h1 { font-size: 1.6rem; font-weight: 650; line-height: 1.2; margin: 0 0 var(--s-3); }
h2 { font-size: 1.15rem; font-weight: 650; line-height: 1.3; margin: var(--s-6) 0 var(--s-3); }
h3 { font-size: 1rem; font-weight: 650; line-height: 1.35; margin: var(--s-4) 0 var(--s-1); }

/* FocusOnNavigate parks focus on the page heading after every navigation, so a screen reader
   announces where it landed. To do that Blazor gives the heading tabindex="-1", and the browser
   then draws a focus ring around it - a stray box around the title for everyone else. The
   heading is not interactive, so there is nothing for a sighted keyboard user to lose here.

   The attribute selector is in here on purpose: a bare h1:focus-visible loses to anything that
   matches the heading through its tabindex, which is how this box came back once already. */
h1, h1:focus, h1:focus-visible, h1[tabindex]:focus, h1[tabindex]:focus-visible { outline: none; }

p { margin: 0 0 var(--s-3); }

a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

.muted { color: var(--muted); }
.small { font-size: .875rem; line-height: 1.45; }

/* Counts and tallies line up column-wise instead of jittering as they change. */
.count, .avatar-more, .badge { font-variant-numeric: tabular-nums; }

/* --- topbar -------------------------------------------------------------- */

.topbar {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--topbar-bg);
    color: var(--topbar-fg);
    padding-top: env(safe-area-inset-top);
}

.topbar-inner {
    max-width: 720px;
    margin: 0 auto;
    padding: 0 var(--s-4);
    display: grid;
    align-items: center;
    /* On a phone there is no room for a name, three nav items and a sign-out button side by
       side, so the nav drops to its own line rather than being squeezed or hidden behind a
       hamburger - the whole app is three pages and all three should stay one tap away. */
    grid-template-columns: 1fr auto;
    grid-template-areas:
        "brand logout"
        "nav   nav";
    gap: 0 var(--s-3);
}

@media (min-width: 640px) {
    .topbar-inner {
        grid-template-columns: auto 1fr auto;
        grid-template-areas: "brand nav logout";
        gap: var(--s-5);
    }
}

.brand {
    grid-area: brand;
    display: flex;
    align-items: center;
    min-height: 52px;
    font-weight: 680;
    font-size: 1.1rem;
    letter-spacing: -.01em;
    color: var(--topbar-fg);
    text-decoration: none;
}

.logout-form { grid-area: logout; margin: 0; }

.topbar .link-button { color: var(--topbar-fg-dim); text-decoration: none; font-weight: 500; }
.topbar .link-button:hover { color: var(--topbar-fg); }

/* The default accent ring is invisible against the bar. */
.topbar a:focus-visible,
.topbar button:focus-visible { outline: 2px solid var(--topbar-fg); outline-offset: 2px; }

.app-nav {
    grid-area: nav;
    display: flex;
    gap: var(--s-1);
    overflow-x: auto;
    padding-bottom: var(--s-2);
    scrollbar-width: none;
}

.app-nav::-webkit-scrollbar { display: none; }

@media (min-width: 640px) {
    .app-nav { padding-bottom: 0; }
}

.app-nav a {
    padding: var(--s-2) var(--s-3);
    min-height: 38px;
    display: flex;
    align-items: center;
    border-radius: var(--r-pill);
    color: var(--topbar-fg-dim);
    text-decoration: none;
    font-size: .95rem;
    font-weight: 500;
    white-space: nowrap;
    transition: background-color .15s var(--ease), color .15s var(--ease);
}

.app-nav a:hover { color: var(--topbar-fg); }

/* A soft pill rather than an underline: it survives the wrap to a second row on a phone, where
   an underline just looks like a stray rule across the bar. */
.app-nav a.active {
    background: var(--topbar-active);
    color: var(--topbar-fg);
    font-weight: 600;
}

/* --- page ---------------------------------------------------------------- */

.app {
    max-width: 720px;
    margin: 0 auto;
    padding: var(--s-5) var(--s-4) env(safe-area-inset-bottom);
}

main { padding-bottom: var(--s-7); }

/* --- surfaces ------------------------------------------------------------ */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: var(--s-5);
    margin-bottom: var(--s-3);
    box-shadow: var(--shadow-sm);
}

/* Cards own their internal rhythm, so the content inside never needs a margin override. */
.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

.card.empty {
    text-align: center;
    color: var(--muted);
    padding: var(--s-7) var(--s-5);
    text-wrap: pretty;
}

.card.empty strong { color: var(--text); }

.empty-emoji {
    font-size: 3.5rem;
    line-height: 1;
    margin: 0 0 var(--s-3);
    /* Emoji render as a flat pictograph; a touch of shadow stops it looking pasted on. */
    filter: drop-shadow(0 4px 10px rgba(22, 28, 24, .16));
}

.notice {
    padding: var(--s-3) var(--s-4);
    border-radius: var(--r-md);
    border: 1px solid var(--border);
    background: var(--surface);
    /* Air above as well as below: a notice that follows a row of buttons - the delete
       confirmation, say - was landing flush against them. The card rules below strip this again
       when the notice happens to be the first or last thing in a card. */
    margin: var(--s-4) 0;
}

.notice > :first-child { margin-top: 0; }
.notice > :last-child { margin-bottom: 0; }

.notice.good { border-left: 3px solid var(--accent); background: var(--accent-soft); }
.notice.bad { border-left: 3px solid var(--red); background: var(--red-soft); }

.pill {
    display: inline-flex;
    align-items: center;
    padding: var(--s-1) var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: var(--surface);
    color: var(--text-soft);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .005em;
}

/* Tinted, because "who is on the board" is the marker a member actually scans the roster for -
   it should outrank the technical admin/inaktiv badges next to it. */
.pill.accent {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent);
}

.pill.small { font-size: .72rem; padding: 2px var(--s-2); }

/* Your own boat place, on Min profil: one or two of them, and the thing you came to the page to
   check. Big enough to read at arm's length, and tinted so it does not look like a caption. */
.pill.big {
    font-size: 1.0625rem;
    padding: var(--s-2) var(--s-4);
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent);
}

.badge {
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 2px var(--s-2);
    border-radius: var(--r-pill);
    background: var(--surface-sunken);
    color: var(--muted);
    border: 1px solid var(--border);
}

/* --- buttons ------------------------------------------------------------- */

.button, button.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    min-height: var(--tap);
    padding: var(--s-3) var(--s-5);
    border: 1px solid transparent;
    border-radius: var(--r-md);
    background: var(--btn-bg);
    color: var(--btn-fg);
    font: inherit;
    font-weight: 600;
    letter-spacing: -.005em;
    text-decoration: none;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: background-color .15s var(--ease), border-color .15s var(--ease),
                box-shadow .15s var(--ease), transform .08s var(--ease);
}

/* The colour matters as much as the background: a secondary button starts out with dark text on
   a light fill, and without resetting it here it keeps that dark text once hover fills it. */
.button:hover:not(:disabled) {
    background: var(--btn-bg-hover);
    color: var(--btn-fg);
    border-color: var(--btn-bg-hover);
    box-shadow: var(--shadow-md);
}

/* A press should feel like one. */
.button:active:not(:disabled) { transform: translateY(1px); box-shadow: var(--shadow-sm); }

.button:disabled { opacity: .5; cursor: default; box-shadow: none; }

.button.secondary {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border-strong);
}

.button.danger { background: transparent; color: var(--red); border-color: var(--border-strong); box-shadow: none; }

/* Turning green on hover would be a strange thing for a delete button to do. Emphasise the
   outline instead, which also keeps the label readable in both themes. */
.button.danger:hover:not(:disabled) {
    background: var(--red-soft);
    color: var(--red);
    border-color: var(--red);
    box-shadow: none;
}

.button.big { width: 100%; font-size: 1.05rem; padding: var(--s-4) var(--s-5); }

.link-button {
    background: none;
    border: 0;
    padding: var(--s-2) 2px;
    min-height: var(--tap);
    font: inherit;
    font-size: .9rem;
    color: var(--link);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.link-button:hover { text-decoration-thickness: 2px; }

.actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }

/* Opt-in, so the primary actions on the forms and the detail page stay on the left. */
.actions.end { justify-content: flex-end; }

.toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    align-items: center;
    margin-bottom: var(--s-4);
}

.toolbar h1 { margin: 0; }
.toolbar .spacer { flex: 1 1 auto; }

/* Medlemmar / Anna Ek - sits above the page heading, not in place of it. */
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--s-2);
    margin-bottom: var(--s-3);
    font-size: .9375rem;
}

.breadcrumb .separator { color: var(--muted); }

/* Where you already are: shown, but not as something to tap. */
.breadcrumb .current { color: var(--muted); overflow-wrap: anywhere; }

/* --- forms --------------------------------------------------------------- */

.field { margin-bottom: var(--s-4); }

.field label {
    display: block;
    font-weight: 600;
    font-size: .95rem;
    margin-bottom: var(--s-2);
    color: var(--text);
}

.field .hint { color: var(--muted); font-size: .875rem; margin: calc(var(--s-1) * -1) 0 var(--s-2); }

/* A date is a short value: at full width it reads as a field waiting for prose. */
.field.planned input { width: auto; min-width: 11rem; max-width: 100%; }

input:not([type=checkbox], [type=radio], [type=file], [type=hidden], [type=submit], [type=button]),
textarea,
select {
    width: 100%;
    min-height: var(--tap);
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    /* 16px or larger, or iOS zooms the page when the field takes focus. */
    font: inherit;
    transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}

input::placeholder, textarea::placeholder { color: var(--muted); opacity: .75; }

input:hover:not(:disabled), textarea:hover, select:hover { border-color: var(--muted); }

/* A ring drawn with box-shadow rather than an outline: it follows the rounded corner instead of
   boxing it, and it can sit tight against the border. */
input:focus-visible, textarea:focus-visible, select:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--focus-ring);
}

textarea { min-height: 112px; resize: vertical; line-height: 1.5; }

/* Everything else keeps a plain, unmissable ring.
 *
 * Deliberately not [tabindex]:focus-visible. That reads as "anything focusable", but the only
 * thing in this app carrying a tabindex is the page heading, which Blazor makes focusable purely
 * so screen readers land on it after a navigation - and the rule then drew a box around every
 * page title. Interactive elements are listed explicitly instead. */
button:focus-visible,
a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.checkbox { display: flex; align-items: center; gap: var(--s-3); min-height: var(--tap); }
.checkbox input { width: 20px; height: 20px; accent-color: var(--accent); }

.choice {
    display: flex;
    gap: var(--s-3);
    align-items: flex-start;
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    margin-bottom: var(--s-2);
    background: var(--surface);
    cursor: pointer;
    transition: border-color .15s var(--ease), background-color .15s var(--ease);
}

.choice:hover { border-color: var(--border-strong); }
.choice input { margin-top: 3px; width: 20px; height: 20px; accent-color: var(--accent); }

.choice.selected {
    border-color: var(--accent);
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 1px var(--accent);
}

.choice .choice-text { display: block; font-weight: 600; }
.choice .choice-text small { display: block; color: var(--muted); font-weight: 400; margin-top: 2px; }

.validation { color: var(--red); font-size: .875rem; margin-top: var(--s-1); }

/* --- task list ----------------------------------------------------------- */

.chips {
    display: flex;
    gap: var(--s-2);
    overflow-x: auto;
    padding-bottom: var(--s-2);
    margin-bottom: var(--s-4);
    scrollbar-width: none;
}

.chips::-webkit-scrollbar { display: none; }

.chip {
    flex: 0 0 auto;
    padding: var(--s-2) var(--s-4);
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: var(--surface);
    color: var(--text-soft);
    font: inherit;
    font-size: .9rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color .15s var(--ease), border-color .15s var(--ease), color .15s var(--ease);
}

.chip:hover { border-color: var(--border-strong); color: var(--text); }

.chip.on {
    background: var(--btn-bg);
    border-color: var(--btn-bg);
    color: var(--btn-fg);
    font-weight: 600;
}

.task {
    display: flex;
    gap: var(--s-4);
    align-items: center;
    padding: var(--s-4);
    margin-bottom: var(--s-2);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    color: inherit;
    transition: border-color .15s var(--ease), box-shadow .15s var(--ease), transform .12s var(--ease);
}

/* Lifts a hair on hover: enough to read as "this is a thing you can open". */
.task:hover {
    border-color: var(--border-strong);
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

.task:active { transform: translateY(0); box-shadow: var(--shadow-sm); }

.task .thumb {
    width: 60px;
    height: 60px;
    flex: 0 0 auto;
    border-radius: var(--r-md);
    object-fit: cover;
    background: var(--surface-sunken);
    /* A hairline inside the image keeps a pale photo from bleeding into the card. */
    box-shadow: inset 0 0 0 1px rgba(22, 28, 24, .08);
}

.task .body { min-width: 0; flex: 1 1 auto; }

.task .title {
    display: block;
    font-weight: 600;
    letter-spacing: -.008em;
    margin-bottom: 3px;
    overflow-wrap: anywhere;
}

.task .meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-3);
    font-size: .85rem;
    color: var(--muted);
}

.task.done { background: var(--surface-sunken); box-shadow: none; }
.task.done .title { color: var(--muted); }
.task.done .thumb { opacity: .7; }

/* Status is carried by the words too, never by the colour alone. */
.tag-done { color: var(--accent); font-weight: 600; }

/* --- avatars ------------------------------------------------------------- */

.avatar {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    color: #fff;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .01em;
    /* Keeps the circles legible where they overlap in a stack. */
    box-shadow: 0 0 0 2px var(--surface), inset 0 0 0 1px rgba(255, 255, 255, .14);
    user-select: none;
}

.avatar-sm { width: 30px; height: 30px; font-size: .68rem; }

.avatar-stack { display: flex; align-items: center; }

/* Overlap, so four helpers take the width of two. */
.avatar-stack .avatar + .avatar { margin-left: -10px; }

.avatar-more {
    flex: 0 0 auto;
    margin-left: var(--s-2);
    font-size: .8rem;
    font-weight: 600;
    color: var(--muted);
    white-space: nowrap;
}

.helpers {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--s-1);
    flex: 0 0 auto;
}

.helpers .count { font-size: .78rem; color: var(--muted); white-space: nowrap; }
.helpers .count.enough { color: var(--accent); font-weight: 600; }

.task.done .avatar { box-shadow: 0 0 0 2px var(--surface-sunken); }

.volunteer-list { display: flex; flex-direction: column; gap: var(--s-3); margin: var(--s-4) 0; }
.volunteer { display: flex; align-items: center; gap: var(--s-3); }

/* --- task detail --------------------------------------------------------- */

.detail-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-3);
    color: var(--muted);
    font-size: .9rem;
    margin-bottom: var(--s-4);
}

.description { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-soft); }

.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--s-3);
    margin: var(--s-4) 0;
}

.gallery figure { margin: 0; }

.gallery img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--r-md);
    background: var(--surface-sunken);
    box-shadow: inset 0 0 0 1px rgba(22, 28, 24, .08);
    transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}

.gallery a:hover img { box-shadow: var(--shadow-md), inset 0 0 0 1px rgba(22, 28, 24, .08); }

.gallery figcaption {
    font-size: .8rem;
    color: var(--muted);
    padding-top: var(--s-1);
}

/* Same reason as in the previews: on its own line under the picture it is removing. */
.gallery figcaption .link-button { display: block; }

.comment { padding: var(--s-4) 0; border-top: 1px solid var(--border); }
.comment:first-of-type { border-top: 0; padding-top: 0; }
.comment .who { font-weight: 600; }
.comment .when { color: var(--muted); font-size: .85rem; margin-left: var(--s-2); }
.comment .body { white-space: pre-wrap; overflow-wrap: anywhere; margin: var(--s-1) 0 0; color: var(--text-soft); }

/* Separates the "write a comment" box from the thread above it. */
.comment-box { margin-top: var(--s-5); }

/* --- members ------------------------------------------------------------- */

/* Top-aligned: an entry can run to three lines once the property and address are filled in,
   and "Ändra" floating in the vertical middle of that reads as unattached. */
.member { display: flex; gap: var(--s-3); align-items: flex-start; padding: var(--s-4) 0; border-top: 1px solid var(--border); }
.member:first-of-type { border-top: 0; padding-top: 0; }
.member .who { flex: 1 1 auto; min-width: 0; }
.member .who .name { font-weight: 600; display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.member .who a { display: inline-block; min-height: 30px; overflow-wrap: anywhere; }

/* --- boat places --------------------------------------------------------- */

.places { display: flex; flex-direction: column; gap: var(--s-2); margin-bottom: var(--s-3); }

.place { display: flex; align-items: center; gap: var(--s-2); }

/* Wide enough for "Väst 3" or "Bryggan A:4", not the full width of the panel. */
.place input { width: 11rem; flex: 0 0 auto; }

.place-add { margin-top: var(--s-2); }

.places-readonly { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* Visually hidden, still read out. The number fields are in a row where a visible label per
   input would be more noise than help. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.member-place { margin-top: 2px; }
/* Kept as written, in case the address field ever becomes multi-line. */
.member-place .address { white-space: pre-line; }
/* Nudged down so the circle sits centred on the name rather than on the cap height. */
.member > .avatar { margin-top: 2px; }

.member.inactive .name { color: var(--muted); }
.member.inactive > .avatar { opacity: .55; }
/* Only the name is struck through - not the badges sitting next to it. */
.member.inactive .name-text { text-decoration: line-through; }

/* --- upload -------------------------------------------------------------- */

.dropzone {
    position: relative;
    border: 1.5px dashed var(--border-strong);
    border-radius: var(--r-lg);
    background: var(--surface-sunken);
    padding: var(--s-5) var(--s-4);
    text-align: center;
    transition: border-color .15s var(--ease), background-color .15s var(--ease);
}

.dropzone:hover { border-color: var(--accent); background: var(--accent-soft); }

/* The real control is invisible, so the ring has to be drawn on the zone around it. */
.dropzone:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }

.dropzone.dragging {
    border-style: solid;
    border-color: var(--accent);
    background: var(--accent-soft);
}

/* Stretched over the whole zone: this is what makes both the click and the drop work, with no
   JavaScript on either path. */
.dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.dropzone.busy .dropzone-input { cursor: default; }

/* Transparent to the pointer, so every click lands on the input underneath it. */
.dropzone-face {
    pointer-events: none;
    display: grid;
    justify-items: center;
    gap: var(--s-2);
}

.dropzone-icon { width: 30px; height: 30px; color: var(--muted); }
.dropzone-label { font-weight: 600; margin: 0; }
.dropzone-face .small { margin: 0; }

.previews { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-3); }

/* A column, so "Ta bort" sits under its own thumbnail rather than alongside it - side by side
   it is not obvious which picture the link belongs to. */
.previews figure { margin: 0; display: flex; flex-direction: column; align-items: center; }

.previews img {
    display: block;
    width: 88px;
    height: 88px;
    object-fit: cover;
    border-radius: var(--r-md);
    background: var(--surface-sunken);
    box-shadow: inset 0 0 0 1px rgba(22, 28, 24, .08);
}

.progress {
    height: 5px;
    background: var(--border);
    border-radius: var(--r-pill);
    overflow: hidden;
    margin-top: var(--s-3);
}

.progress span {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: inherit;
    transition: width .2s var(--ease);
}

.upload-status { margin: var(--s-2) 0 0; }

/* --- login --------------------------------------------------------------- */

.login { max-width: 400px; margin: 6vh auto 0; }
.login h1 { text-align: center; }
.login .lead { text-align: center; color: var(--muted); margin-bottom: var(--s-5); text-wrap: pretty; }
.login .card { box-shadow: var(--shadow-lg); padding: var(--s-5); }

/* --- Blazor's own chrome -------------------------------------------------- */

#blazor-error-ui {
    position: fixed;
    inset: auto 0 0 0;
    display: none;
    padding: var(--s-3) var(--s-4);
    background: #f7e6a2;
    color: #1a1d1b;
    box-shadow: var(--shadow-lg);
}

.blazor-error-boundary { padding: var(--s-4); background: var(--red-soft); border-radius: var(--r-md); }

/* --- motion ---------------------------------------------------------------
 * Some people get motion sick from exactly the sort of lift and slide added above.
 */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }

    .task:hover { transform: none; }
    .button:active:not(:disabled) { transform: none; }
}
