/**
 * Cards
 *
 * A card is a cream surface on the teal ground. It sets the ink text colour for
 * everything inside it, which is what stops each page from having to repaint
 * its own text — the reason eleven page stylesheets existed.
 *
 * One shadow, one radius. No inset neumorphic wells: numbers sit on the card
 * face with a hairline between them.
 */

.card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--card-face);
    border: none;
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-card);
    color: var(--text-on-light);
    overflow: hidden;
}

/*
 * The card is a flex column, so its children default to min-width:auto and
 * would be sized by their widest descendant — a wide table would push the page
 * sideways instead of scrolling inside its own box.
 */
.card > * {
    min-width: 0;
}

/*
 * Every cream surface in the product, named once. Each redefines the surface
 * contract from 1-variables.css for its contents, which is what stops each
 * page from repainting its own text — the reason eleven page stylesheets
 * existed. Components read var(--surface-*) and never need to know which
 * surface they landed on.
 */
:is(.card, .on-light, .event-card, .auth-card, .modal-card, .modal-content, .confirmation-card, .table-card, .journey-feedback, .empty-state, .card-empty, .alert, .send-confirm-dialog, .next-step-card) {
    --surface-text: var(--text-on-light);
    --surface-text-muted: var(--text-on-light-muted);
    --surface-border: var(--border-on-light);
    --surface-hover: rgba(26, 77, 77, 0.06);
    --surface-link: var(--color-red-dark);
    --surface-link-hover: var(--color-red-deep);
    --surface-success: var(--color-success);
    --surface-warning: var(--color-gold-ink);
    --surface-danger: var(--color-danger);
    --surface-info: var(--color-info);

    color: var(--surface-text);
}

:is(.card, .on-light, .event-card, .auth-card, .modal-card, .modal-content, .confirmation-card, .table-card, .journey-feedback, .empty-state, .card-empty, .alert, .send-confirm-dialog, .next-step-card) a:not(.btn) {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.text-muted,
.form-text,
.card small {
    color: var(--surface-text-muted);
}

.card-header {
    padding: var(--space-5) var(--space-5);
    border-bottom: 1px solid var(--border-on-light-hairline);
    background: transparent;
    color: inherit;
    font-family: var(--font-display);
    font-size: var(--display-sm);
    font-weight: var(--font-weight-normal);
    letter-spacing: var(--tracking-display);
    line-height: var(--line-height-tight);
}

.card-header > h1,
.card-header > h2,
.card-header > h3,
.card-header > h4 {
    font-size: inherit;
}

/*
 * A header that carries its own actions: the title takes the slack and the
 * buttons sit at the right, at the same optical weight they have anywhere else.
 * The title keeps the header's display face; the buttons opt back into body
 * type, because they inherit the header's serif otherwise.
 */
.card-header-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.card-header-title {
    flex: 1 1 auto;
    min-width: 0;
}

.card-header-row .btn {
    font-family: var(--font-body);
    letter-spacing: normal;
}

/*
 * A count beside a header title — "142 of 150".
 *
 * It sits after the title rather than taking its own row, and it is body type
 * and muted, because it is a fact about the card and not a second heading. The
 * page only renders it as an exchange approaches its ceiling; a family of six
 * has no use for it, and something that is always on screen is something
 * nobody reads on the day it starts to matter.
 */
.card-header-count {
    font-family: var(--font-body);
    font-size: var(--font-size-sm);
    font-weight: 400;
    letter-spacing: normal;
    color: var(--text-on-light-muted);
    white-space: nowrap;
}

.card-header-count.is-full {
    color: var(--color-danger);
    font-weight: 600;
}

/* An avatar in a header keeps the header's display face for the name and drops
   back to body type for anything secondary beside it. */
.card-header .avatar-row-text > span:first-child {
    font-family: inherit;
    font-size: inherit;
}

.card-header-note {
    color: var(--text-on-light-muted);
    font-family: var(--font-body);
    font-size: var(--font-size-sm);
    letter-spacing: normal;
}

.card-body {
    padding: var(--space-6);
}

.card-body-sm {
    padding: var(--space-5);
}

.card-body-lg {
    padding: var(--space-8);
}

.card-body-no-padding {
    padding: 0;
}

.card-footer {
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border-on-light-hairline);
    background: transparent;
}

/*
 * The header variants used to be five different coloured slabs. They are now a
 * single cream header distinguished by a rule, because colour in this system
 * carries state and a header is not a state.
 */
.card-header-primary,
.card-header-secondary,
.card-header-success,
.card-header-info,
.card-header-light,
.card-header.bg-primary,
.card-header.bg-secondary,
.card-header.bg-success,
.card-header.bg-info,
.card-header.bg-light,
.card-header.bg-warning {
    background: transparent;
    color: var(--text-on-light);
}

/* ============================================
   ATTENTION EDGE

   A 3px bar on the left edge is how a card says it needs something. It is the
   only place the bright accent red appears, and it is never text.
   ============================================ */

.card-border-left,
.card-needs-you {
    border-left: 3px solid var(--color-red);
}

.card-border-left-success,
.card-done {
    border-left: 3px solid var(--color-success-fill);
}

.card-border-left-secondary,
.card-in-progress {
    border-left: 3px solid var(--color-gold);
}

.card-border-left-error {
    border-left: 3px solid var(--color-danger);
}

/* ============================================
   BEHAVIOUR
   ============================================ */

.card-hover,
.card-clickable {
    transition: box-shadow var(--duration-fast) var(--easing);
}

.card-hover:hover,
.card-clickable:hover {
    box-shadow: var(--shadow-modal);
}

.card-clickable {
    cursor: pointer;
}

.card-clickable:focus-within {
    box-shadow: var(--shadow-card), var(--focus-ring);
}

/* ============================================
   LAYOUT
   ============================================ */

.card-grid {
    display: grid;
    gap: 22px;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.card-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.card-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.card-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1024px) {
    .card-grid-3,
    .card-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
    .card-grid,
    .card-grid-2,
    .card-grid-3,
    .card-grid-4 { grid-template-columns: minmax(0, 1fr); }
}

.card-narrow { max-width: 480px; }
.card-wide { max-width: 960px; }
.card-full { width: 100%; }

.card-centered {
    margin-left: auto;
    margin-right: auto;
}

.card-list {
    display: flex;
    flex-direction: column;
}

/* Rows inside a card are separated by a hairline, not by a well. */
.card-list-item {
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--border-on-light-hairline);
}

.card-list-item:last-child {
    border-bottom: none;
}

/* ============================================
   EMPTY STATE

   The zero-events dashboard and the two-participant event page are the moments
   a new organiser decides whether this is any good, so they are a designed
   state rather than a sentence.
   ============================================ */

/*
 * An empty state is the CONTENTS of a card, not a card.
 *
 * It used to carry its own face, radius and shadow, and every caller nests it
 * inside .card > .card-body — so every empty state in the product rendered as a
 * card floating inside a card, casting a shadow onto the one behind it. It
 * inherits the surface it sits on now, and the standalone rule below covers the
 * one case that is genuinely on its own.
 */
.card-empty,
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-3);
    padding: var(--space-12) var(--space-6);
    color: var(--text-on-light);
}

/* Not inside a card: give it the card face it would otherwise have had. */
.empty-state-standalone {
    background: var(--card-face);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-card);
}

/*
 * A group of ornaments, sized here rather than at the call site. The dashboard
 * set 96/64/48px inline, which reads as three unrelated images rather than one
 * arrangement; these sit on a shared baseline and step down gently.
 */
.empty-state-scene {
    display: inline-flex;
    align-items: flex-end;
    gap: var(--space-4);
}

.empty-state-scene img {
    height: auto;
    object-fit: contain;
}

.card-empty-icon,
.empty-state-icon {
    width: 96px;
    height: 96px;
    object-fit: contain;
}

.card-empty-title,
.empty-state-title {
    font-family: var(--font-display);
    font-size: var(--display-sm);
    font-weight: var(--font-weight-normal);
    letter-spacing: var(--tracking-display);
}

.card-empty-description,
.empty-state-description {
    max-width: 44ch;
    color: var(--text-on-light-muted);
}

/* ============================================
   AUTH CARD

   The sign-in and create-account card: a wider radius and the modal shadow,
   because it is the only thing on the page.
   ============================================ */

.auth-card {
    width: 100%;
    max-width: 560px;
    /*
     * Centre it. Below 960px .auth-layout collapses to one column and
     * .auth-container stops placing the card, but the card kept a 560px cap
     * with no horizontal margin — so at 768 it pinned to the left of a 736px
     * column with 192px of dead space beside it, on every screen in the flow.
     */
    margin-inline: auto;
    background: var(--card-face);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-modal);
    color: var(--text-on-light);
    overflow: hidden;
}

.auth-card-header {
    padding: var(--space-8) var(--space-8) var(--space-5);
}

.auth-card-header h1,
.auth-card-header h2 {
    font-size: 2.25rem;   /* 36px */
    line-height: var(--line-height-display);
}

.auth-card-body {
    padding: 0 var(--space-8) var(--space-8);
}

/*
 * The footer holds one link on most auth cards and two on login, and it set no
 * layout at all — so login's two ran together into a single underlined string,
 * "Don't have an account? Sign up Forgotten your password?", which at 390px
 * wrapped mid-phrase and split the second link over two lines. A column with a
 * gap keeps one link looking the same as it always did.
 */
.auth-card-footer {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-5) var(--space-8);
    border-top: 1px solid var(--border-on-light-hairline);
    color: var(--text-on-light-muted);
    font-size: var(--font-size-sm);
}

/* ============================================
   LOADING

   Skeleton rows at the real row height, so the page does not reflow when the
   content lands. No spinners in lists.
   ============================================ */

.skeleton-row {
    height: 56px;
    border-radius: var(--radius-md);
    background: linear-gradient(
        90deg,
        rgba(26, 77, 77, 0.06) 25%,
        rgba(26, 77, 77, 0.12) 37%,
        rgba(26, 77, 77, 0.06) 63%
    );
    background-size: 400% 100%;
    animation: skeleton-sweep 1400ms var(--easing) infinite;
}

@keyframes skeleton-sweep {
    from { background-position: 100% 50%; }
    to { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .skeleton-row { animation: none; }
}
