/* Structure and controls. Mobile width first at 375px. Desktop is a wider column and nothing
   more. Colours and the brand mark live in brand.css. */

:root {
    --gutter: 16px;
    --column: 640px;

    /* Spacing scale. Things that belong together sit on the small steps, and sections are
       separated by the large ones, so grouping reads before any word does. */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    --space-7: 48px;

    --tap: 48px;
}

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

html {
    -webkit-text-size-adjust: 100%;
    background: var(--brand-paper);
}

body {
    margin: 0;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 17px;
    line-height: 1.5;
    color: var(--brand-ink);
    background: var(--brand-paper);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}

/* Header. Says which group you are in, so a parent who opened the wrong link knows at once. */

.app-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--brand-ink);
    color: #ffffff;
    padding: 0 var(--gutter);
}

.app-header > .wrap {
    display: flex;
    align-items: center;
    min-height: 56px;
    gap: var(--space-3);
}

.header-title {
    color: #ffffff;
    font-weight: 750;
    font-size: 1.0625rem;
    letter-spacing: -0.01em;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Inside a group the group's name replaces the product's. The page supplies the title and this
   rule hides the product mark, so no page has to remember to hide it. */
.app-header > .wrap:has(.header-title) .brand {
    display: none;
}

.app-main {
    padding: var(--space-5) var(--gutter) var(--space-7);
}

.app-header > .wrap,
.app-main > .wrap {
    max-width: var(--column);
    margin: 0 auto;
}

/* Type. One family from the system, with weight and size doing the work a web font would. */

h1 {
    font-size: 1.75rem;
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -0.025em;
    margin: 0 0 var(--space-2);
}

h1:focus {
    outline: none;
}

/* Section labels. Small and spaced, so a long organizer page scans as a set of parts. */
h2 {
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--brand-muted);
    margin: var(--space-6) 0 var(--space-3);
}

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

.lead {
    font-size: 1.125rem;
    line-height: 1.45;
}

.muted {
    color: var(--brand-muted);
}

.small {
    font-size: 0.9375rem;
}

/* Counts and times line up when they sit in a column. */
.numeric {
    font-variant-numeric: tabular-nums;
}

.spaced {
    margin-top: var(--space-5);
}

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

:focus-visible {
    outline: 3px solid var(--brand-accent);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Buttons. Ink is the one thing to do on a screen. Outlined is everything else. */

.button,
button,
input[type="submit"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: var(--tap);
    padding: 12px 20px;
    border: 1px solid var(--brand-ink);
    border-radius: var(--brand-radius-small);
    background: var(--brand-ink);
    color: #ffffff;
    font: inherit;
    font-weight: 650;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: transform 80ms ease, background-color 120ms ease;
}

.button:active,
button:active {
    transform: translateY(1px);
}

.button.secondary,
button.secondary {
    background: var(--brand-surface);
    border-color: var(--brand-field);
    color: var(--brand-ink);
}

.button.block,
button.block {
    width: 100%;
}

@media (hover: hover) {
    .button:hover,
    button:hover {
        background: #0b1528;
    }

    .button.secondary:hover,
    button.secondary:hover {
        background: var(--brand-tint);
    }
}

/* Forms. White fields on the warm page, so every box you can type into is plain to see. */

label {
    display: block;
    font-size: 0.9375rem;
    font-weight: 650;
    margin: 0 0 var(--space-2);
}

.field {
    margin: 0 0 var(--space-4);
}

/* Matched by exclusion, because Blazor's input components leave the type attribute off. */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="hidden"]),
textarea,
select {
    display: block;
    width: 100%;
    min-height: var(--tap);
    padding: 11px 14px;
    border: 1px solid var(--brand-field);
    border-radius: var(--brand-radius-small);
    background: var(--brand-surface);
    color: var(--brand-ink);
    /* 16px or larger stops iOS zooming the page when a field takes focus. */
    font-size: 17px;
    font-family: inherit;
    line-height: 1.35;
}

input::placeholder,
textarea::placeholder {
    color: var(--brand-muted);
    opacity: 0.8;
}

textarea {
    min-height: 168px;
    resize: vertical;
}

input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: 3px solid var(--brand-accent);
    outline-offset: 0;
    border-color: var(--brand-accent);
}

form > button[type="submit"],
form > .button {
    margin-top: var(--space-2);
}

/* Panels. A static card holds information and is not a target. */

.card {
    position: relative;
    background: var(--brand-surface);
    border: 1px solid var(--brand-line);
    border-radius: var(--brand-radius);
    padding: var(--space-4);
    margin: 0 0 var(--space-3);
}

.card > :last-child {
    margin-bottom: 0;
}

.card.quiet {
    background: var(--brand-tint);
    border-color: transparent;
}

/* A card that is one tap. It carries a chevron and lifts, so it never reads as a static card. */

.card.block-link {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-right: calc(var(--space-4) + 24px);
    color: var(--brand-ink);
    text-decoration: none;
    box-shadow: 0 1px 2px rgb(20 33 61 / 0.06), 0 2px 8px rgb(20 33 61 / 0.05);
    -webkit-tap-highlight-color: transparent;
}

.card.block-link::after {
    content: "";
    position: absolute;
    right: var(--space-4);
    top: 50%;
    width: 9px;
    height: 9px;
    border-top: 2px solid var(--brand-muted);
    border-right: 2px solid var(--brand-muted);
    transform: translateY(-50%) rotate(45deg);
}

.card.block-link:active {
    background: var(--brand-tint);
}

@media (hover: hover) {
    .card.block-link:hover {
        border-color: var(--brand-field);
    }
}

/* A line in a list, with its action beside it. Stacks when the name runs long. */

.card.row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
}

.card.row .button {
    min-height: 44px;
    padding: 8px 16px;
}

.card.row > form {
    flex: 1 1 100%;
}

.row-actions {
    display: flex;
    gap: var(--space-2);
}

.row-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 60%;
}

.row-name {
    font-weight: 650;
    overflow-wrap: anywhere;
}

.row-detail {
    font-size: 0.9375rem;
    color: var(--brand-muted);
}

/* A list of rows reads as one block, with the gaps between rows kept small. */
.stack > .card {
    margin-bottom: var(--space-2);
}

/* Nothing here yet. Dashed, so it reads as a place something will go rather than a thing. */

.empty {
    border: 1px dashed var(--brand-field);
    border-radius: var(--brand-radius);
    padding: var(--space-4);
    color: var(--brand-muted);
    font-size: 0.9375rem;
    margin: 0 0 var(--space-3);
}

/* The claim bar. Sits at the top of a group page and never covers what someone came to read.
   Before anyone is picked it carries the accent, because it is the one thing to do. */

.whobar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin: 0 0 var(--space-5);
    padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
    background: var(--brand-surface);
    border: 1px solid var(--brand-line);
    border-left: 4px solid var(--brand-accent);
    border-radius: var(--brand-radius);
    font-weight: 600;
}

.whobar.known {
    background: var(--brand-tint);
    border-color: transparent;
    border-left-color: transparent;
    font-weight: 400;
}

.whobar .button {
    min-height: 44px;
    padding: 8px 16px;
}

/* A name to tap on the picker. The whole row is the target, not the little circle. */

.choices {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
}

.choice {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 56px;
    margin: 0;
    padding: var(--space-2) var(--space-4);
    background: var(--brand-surface);
    border: 1px solid var(--brand-line);
    border-radius: var(--brand-radius);
    font-size: 1.0625rem;
    font-weight: 500;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.choice input[type="radio"],
.choice input[type="checkbox"] {
    width: 22px;
    height: 22px;
    margin: 0;
    flex: none;
    accent-color: var(--brand-accent);
}

.choice:has(input:checked) {
    border-color: var(--brand-accent);
    box-shadow: inset 0 0 0 1px var(--brand-accent);
}

.choice span {
    overflow-wrap: anywhere;
}

/* A link someone has to keep or paste. Breaks anywhere so it never pushes the page sideways. */

.notice {
    background: var(--brand-surface);
    border: 1px solid var(--brand-accent);
    border-radius: var(--brand-radius);
    padding: var(--space-4);
    margin: 0 0 var(--space-5);
}

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

.link-text {
    display: block;
    margin: 0 0 var(--space-3);
    padding: var(--space-3);
    background: var(--brand-paper);
    border-radius: var(--brand-radius-small);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.875rem;
    line-height: 1.45;
    word-break: break-all;
    color: var(--brand-ink);
}

/* An itinerary. Each day has its own heading, and each post keeps its time in a column down the
   left, so the day reads top to bottom like a printed schedule. */

.day {
    font-size: 1.0625rem;
    font-weight: 750;
    line-height: 1.3;
    margin: var(--space-5) 0 var(--space-2);
}

/* A post on the itinerary. The whole card is one tap to the post, with the same chevron as any
   other tappable card. A form cannot sit inside a link, so the link stays at the top and its
   ::before stretches over the whole card. The answer buttons sit above that layer as their own
   targets, and the gaps between them fall through to the link. */

.card.post-card {
    padding: 0;
    box-shadow: 0 1px 2px rgb(20 33 61 / 0.06), 0 2px 8px rgb(20 33 61 / 0.05);

    /* Clears the sticky header when an answer brings the page back to this card. */
    scroll-margin-top: 72px;
}

.post-card:has(.post-link:active) {
    background: var(--brand-tint);
}

.post-card:has(.post-link:focus-visible) {
    outline: 3px solid var(--brand-accent);
    outline-offset: 2px;
}

.post-link {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-4) calc(var(--space-4) + 24px) var(--space-4) var(--space-4);
    color: var(--brand-ink);
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}

.post-link:focus-visible {
    outline: none;
}

.post-link::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--brand-radius);
}

.post-link::after {
    content: "";
    position: absolute;
    right: var(--space-4);
    top: 50%;
    width: 9px;
    height: 9px;
    border-top: 2px solid var(--brand-muted);
    border-right: 2px solid var(--brand-muted);
    transform: translateY(-50%) rotate(45deg);
}

.post-link.timed {
    display: grid;
    grid-template-columns: 4.75rem 1fr;
    column-gap: var(--space-3);
    align-items: baseline;
}

.timed .clock {
    grid-row: 1 / span 2;
    font-weight: 650;
    color: var(--brand-ink);
}

.timed .row-name,
.timed .row-detail {
    grid-column: 2;
}

.post-card > .quick {
    position: relative;
    z-index: 1;
    padding: 0 var(--space-4) var(--space-4);
    pointer-events: none;
}

.post-card > .quick button {
    pointer-events: auto;
}

/* Answers. The colour names the answer and the word says it too, so colour is never the only
   signal. */

.answer-head {
    font-weight: 700;
    margin: 0 0 var(--space-2);
}

.answer-head.in {
    color: var(--brand-in);
}

.answer-head.maybe {
    color: var(--brand-maybe);
}

.answer-head.out {
    color: var(--brand-out);
}

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

.names > li {
    padding: 2px 0;
    overflow-wrap: anywhere;
}

/* In, maybe, and out. Outlined until chosen, then filled with the answer's colour. */

.answer-buttons {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
}

button.answer {
    min-height: 44px;
    padding: 8px 12px;
    background: var(--brand-surface);
    border-color: var(--brand-field);
    color: var(--brand-ink);
}

button.answer.in.chosen {
    background: var(--brand-in);
    border-color: var(--brand-in);
    color: #ffffff;
}

button.answer.maybe.chosen {
    background: var(--brand-maybe);
    border-color: var(--brand-maybe);
    color: #ffffff;
}

button.answer.out.chosen {
    background: var(--brand-out);
    border-color: var(--brand-out);
    color: #ffffff;
}

/* The small round version on the itinerary. The icon takes the answer's colour even before it is
   chosen, so the three read apart at a glance. */

.post-card > .quick:has(.compact) {
    margin-top: calc(-1 * var(--space-2));
    padding-bottom: var(--space-3);
}

.answer-buttons.compact {
    display: flex;
    justify-content: flex-start;
    gap: var(--space-2);
}

.compact button.answer {
    width: 44px;
    height: 44px;
    min-height: 44px;
    padding: 0;
    border-radius: 50%;
    border-color: var(--brand-line);
}

.compact button.answer svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.compact button.answer svg .dot {
    fill: currentColor;
    stroke: none;
}

.compact button.answer.in:not(.chosen) {
    color: var(--brand-in);
}

.compact button.answer.maybe:not(.chosen) {
    color: var(--brand-maybe);
}

.compact button.answer.out:not(.chosen) {
    color: var(--brand-out);
}

@media (hover: hover) {
    button.answer:not(.chosen):hover {
        background: var(--brand-tint);
    }

    .post-card:has(.post-link:hover) {
        background: var(--brand-tint);
    }
}

/* Money. What someone owes sits in the accent's border so it is not missed, and turns to the "in"
   green once it is all paid. Paid is a word as well as a colour everywhere it appears. */

.card.tab {
    display: flex;
    flex-direction: column;
    gap: 2px;
    border-left: 4px solid var(--brand-accent);
}

.card.tab.settled {
    border-left-color: var(--brand-in);
}

.owe {
    margin: var(--space-3) 0 0;
    font-weight: 650;
}

.owe.paid,
.paid-state.paid {
    color: var(--brand-in);
}

.paid-state {
    font-size: 0.9375rem;
    font-weight: 650;
    color: var(--brand-muted);
}

.button.edit-post {
    min-height: 44px;
    padding: 8px 16px;
    margin: 0 0 var(--space-3);
}

/* A one-button form sits beside the name, not on its own line like an edit form. */
.card.row > form.paid-form {
    flex: none;
}

button.paid-toggle {
    min-height: 44px;
    padding: 8px 16px;
    background: var(--brand-surface);
    border-color: var(--brand-field);
    color: var(--brand-ink);
}

button.paid-toggle.chosen {
    background: var(--brand-in);
    border-color: var(--brand-in);
    color: #ffffff;
}

@media (hover: hover) {
    button.paid-toggle:not(.chosen):hover {
        background: var(--brand-tint);
    }

    button.paid-toggle.chosen:hover {
        background: var(--brand-in);
    }
}

/* A room number beside a name. */

.room {
    font-weight: 650;
    overflow-wrap: anywhere;
}

/* A native fold-out for a field most people never need. */

.fold {
    margin: 0 0 var(--space-4);
}

.fold > summary {
    min-height: var(--tap);
    display: flex;
    align-items: center;
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--brand-link);
    cursor: pointer;
}

.fold[open] > summary {
    margin-bottom: var(--space-2);
}

/* A view setting drawn as a switch. The whole row is the target, and the knob sits to the right
   when the setting is on. */

.toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    min-height: var(--tap);
    margin: 0 0 var(--space-2);
    color: var(--brand-ink);
    font-size: 0.9375rem;
    font-weight: 600;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}

.toggle .track {
    position: relative;
    flex: none;
    width: 46px;
    height: 28px;
    border-radius: 14px;
    background: var(--brand-field);
}

.toggle .knob {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #ffffff;
    box-shadow: 0 1px 2px rgb(20 33 61 / 0.25);
}

.toggle.on .track {
    background: var(--brand-in);
}

.toggle.on .knob {
    left: 21px;
}

/* A note someone typed. Their line breaks are kept, so a list stays a list. */

.note {
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/* A line of help under a field. */

.hint {
    margin: var(--space-1) 0 0;
}

/* Numbered steps on the front page. The number sits in a circle so the order reads first. */

.steps {
    list-style: none;
    counter-reset: step;
    margin: var(--space-5) 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.steps > li {
    counter-increment: step;
    display: grid;
    grid-template-columns: 32px 1fr;
    column-gap: var(--space-3);
    align-items: start;
}

.steps > li::before {
    content: counter(step);
    grid-row: span 2;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--brand-ink);
    color: #ffffff;
    font-weight: 750;
    font-size: 0.9375rem;
}

/* A short label above a page title that says what kind of page this is. */

.eyebrow {
    margin: 0 0 var(--space-2);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--brand-accent);
}

/* The way back, above a page title. Link-coloured and thumb-sized, with the cards' chevron
   turned to point back, so it reads as the one way out of a page. */

.crumb {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap);
    margin: calc(-1 * var(--space-2)) 0 var(--space-1);
    font-size: 1rem;
    font-weight: 650;
    color: var(--brand-link);
    text-decoration: none;
}

.crumb::before {
    content: "";
    width: 9px;
    height: 9px;
    border-left: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
}

/* Validation, from the Blazor form components. */

.valid.modified:not([type=checkbox]) {
    border-color: var(--brand-in);
}

.invalid {
    border-color: var(--brand-accent) !important;
}

.validation-message {
    display: block;
    margin-top: var(--space-1);
    color: var(--brand-accent);
    font-size: 0.9375rem;
    font-weight: 600;
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}
