/*
 * Goal Attacker design system: components.
 *
 * Every class carries the ga- prefix: Bootstrap 2 and custom.css already own
 * .btn, .label, .alert, .table, .well and friends, and a same-named class here
 * would change screens that have not been migrated. (custom.css also has the
 * older ga-reader-* classes of the attachment reader; they are not part of
 * this system.) Values come only from tokens in ga-tokens.css: no color, no
 * px size. The only literal lengths allowed are inside @media conditions,
 * where a custom property cannot be used.
 *
 * Bootstrap 2 styles bare elements (a, label, input, select, textarea, table)
 * with specificity (0,1,1) and (0,2,1) on :focus. Form controls below are
 * therefore also written as input.ga-input / select.ga-input /
 * textarea.ga-input so that, loaded after Bootstrap, they win ties.
 *
 * Reference: docs/design-system.md. Showcase: admin/design-system. A new
 * component is added here, to the showcase template and to the doc in one go.
 */

/* ── Layout helpers ─────────────────────────────────────────────────────── */
.ga-stack { display: flex; flex-direction: column; gap: var(--ga-space-4); }
.ga-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ga-space-2); }
.ga-stack[hidden], .ga-row[hidden] { display: none; }
.ga-muted { color: var(--ga-text-muted); }
.ga-title {
    margin: 0;
    font-size: var(--ga-text-xl);
    font-weight: var(--ga-weight-bold);
    line-height: var(--ga-leading-tight);
    color: var(--ga-text);
}
.ga-sr-only {
    position: absolute;
    width: var(--ga-border-w);
    height: var(--ga-border-w);
    margin: calc(-1 * var(--ga-border-w));
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ── Buttons ────────────────────────────────────────────────────────────────
   One main action per block: ga-btn--primary; the rest are plain ga-btn. */
.ga-btn {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ga-space-2);
    min-height: var(--ga-tap-min);
    margin: 0;
    padding: 0 var(--ga-space-4);
    border: var(--ga-border-w) solid var(--ga-line-strong);
    border-radius: var(--ga-radius-sm);
    background: var(--ga-surface);
    color: var(--ga-text);
    font-family: inherit;
    font-size: var(--ga-text-sm);
    font-weight: var(--ga-weight-semibold);
    line-height: var(--ga-leading-tight);
    text-decoration: none;
    text-shadow: none;
    box-shadow: none;
    cursor: pointer;
    white-space: nowrap;
}
.ga-btn:hover, .ga-btn:focus { border-color: var(--ga-text-muted); background: var(--ga-surface-sunken); color: var(--ga-text); text-decoration: none; }
.ga-btn:focus-visible { outline: none; box-shadow: var(--ga-focus-ring); }
.ga-btn--primary { background: var(--ga-accent); border-color: var(--ga-accent); color: var(--ga-text-inverse); }
.ga-btn--primary:hover, .ga-btn--primary:focus { background: var(--ga-accent-hover); border-color: var(--ga-accent-hover); color: var(--ga-text-inverse); }
.ga-btn--danger { color: var(--ga-bad); border-color: var(--ga-bad); }
.ga-btn--danger:hover, .ga-btn--danger:focus { color: var(--ga-bad); border-color: var(--ga-bad); background: var(--ga-bad-soft); }
.ga-btn--ghost { border-color: transparent; background: transparent; color: var(--ga-accent); }
.ga-btn--ghost:hover, .ga-btn--ghost:focus { border-color: transparent; background: var(--ga-accent-soft); color: var(--ga-accent-hover); }
.ga-btn--sm { min-height: var(--ga-tap-compact); padding: 0 var(--ga-space-3); font-size: var(--ga-text-xs); }
.ga-btn[hidden] { display: none; }
.ga-btn[disabled], .ga-btn[aria-disabled="true"] { opacity: var(--ga-opacity-disabled); cursor: not-allowed; }
@media (pointer: coarse) {
    .ga-btn--sm { min-height: var(--ga-tap-min); min-width: var(--ga-tap-min); }
}

/* ── Chip: a status in one word ─────────────────────────────────────────── */
.ga-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--ga-space-1);
    padding: var(--ga-space-0) var(--ga-space-3);
    border: var(--ga-border-w) solid var(--ga-line);
    border-radius: var(--ga-radius-pill);
    background: var(--ga-surface-hover);
    color: var(--ga-text);
    font-size: var(--ga-text-xs);
    font-weight: var(--ga-weight-semibold);
    line-height: var(--ga-leading-tight);
    white-space: nowrap;
}
.ga-chip--accent { background: var(--ga-accent-soft); border-color: var(--ga-accent-line); color: var(--ga-accent-hover); }
.ga-chip--ok { background: var(--ga-ok-soft); border-color: var(--ga-ok-line); color: var(--ga-ok); }
.ga-chip--warn { background: var(--ga-warn-soft); border-color: var(--ga-warn-line); color: var(--ga-warn); }
.ga-chip--bad { background: var(--ga-bad-soft); border-color: var(--ga-bad-line); color: var(--ga-bad); }
.ga-chip--info { background: var(--ga-info-soft); border-color: var(--ga-info-line); color: var(--ga-info); }

/* ── Badge: a small mark next to a heading (lock, counter) ──────────────── */
.ga-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--ga-space-1);
    padding: var(--ga-space-0) var(--ga-space-2);
    border-radius: var(--ga-radius-sm);
    background: var(--ga-info-soft);
    color: var(--ga-info);
    font-size: var(--ga-text-xs);
    font-weight: var(--ga-weight-semibold);
    line-height: var(--ga-leading-tight);
    vertical-align: middle;
    white-space: nowrap;
}
.ga-badge--count { min-width: var(--ga-size-counter); justify-content: center; border-radius: var(--ga-radius-pill); background: var(--ga-bad); color: var(--ga-text-inverse); }

/* ── Card ───────────────────────────────────────────────────────────────── */
.ga-card {
    box-sizing: border-box;
    padding: var(--ga-space-4);
    border: var(--ga-border-w) solid var(--ga-line);
    border-radius: var(--ga-radius-md);
    background: var(--ga-surface);
    color: var(--ga-text);
}
.ga-card__title { margin: 0 0 var(--ga-space-2); font-size: var(--ga-text-lg); font-weight: var(--ga-weight-bold); line-height: var(--ga-leading-tight); }
.ga-card__hint { margin: 0; color: var(--ga-text-muted); font-size: var(--ga-text-xs); font-weight: var(--ga-weight-regular); }
.ga-card--sunken { background: var(--ga-surface-sunken); }
.ga-card--hero { padding: var(--ga-space-5); border-color: transparent; border-radius: var(--ga-radius-lg); background: var(--ga-surface-hover); }
.ga-card--raised { border-color: transparent; box-shadow: var(--ga-shadow-md); }
.ga-card--accent { border-color: var(--ga-accent-line); background: var(--ga-accent-soft); }

/* ── Alert: a message about a result or a problem ───────────────────────── */
.ga-alert {
    box-sizing: border-box;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--ga-space-1) var(--ga-space-2);
    padding: var(--ga-space-3) var(--ga-space-4);
    border: var(--ga-border-w) solid var(--ga-line);
    border-radius: var(--ga-radius-sm);
    background: var(--ga-surface-sunken);
    color: var(--ga-text);
    font-size: var(--ga-text-md);
}
.ga-alert__title { font-weight: var(--ga-weight-bold); }
.ga-alert--ok { background: var(--ga-ok-soft); border-color: var(--ga-ok-line); color: var(--ga-ok); }
.ga-alert--warn { background: var(--ga-warn-soft); border-color: var(--ga-warn-line); color: var(--ga-warn); }
.ga-alert--bad { background: var(--ga-bad-soft); border-color: var(--ga-bad-line); color: var(--ga-bad); }
.ga-alert--info { background: var(--ga-info-soft); border-color: var(--ga-info-line); color: var(--ga-info); }

/* ── Table: scrolls inside its frame, never pushes the page sideways ────── */
.ga-table-wrap {
    box-sizing: border-box;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: var(--ga-border-w) solid var(--ga-line);
    border-radius: var(--ga-radius-md);
    background: var(--ga-surface);
}
.ga-table-wrap:focus-visible { outline: none; box-shadow: var(--ga-focus-ring); }
.ga-table { width: 100%; margin: 0; border-collapse: collapse; font-size: var(--ga-text-sm); color: var(--ga-text); }
.ga-table th, .ga-table td {
    padding: var(--ga-space-1) var(--ga-space-3);
    border: 0;
    border-bottom: var(--ga-border-w) solid var(--ga-line);
    text-align: left;
    vertical-align: top;
}
.ga-table thead th {
    background: var(--ga-surface-hover);
    border-bottom: var(--ga-border-w-strong) solid var(--ga-line-strong);
    font-weight: var(--ga-weight-bold);
}
.ga-table tbody tr:nth-child(even) { background: var(--ga-surface-sunken); }
.ga-table tbody tr:hover { background: var(--ga-row-hover); }
.ga-table tbody tr:last-child td { border-bottom: 0; }
.ga-table--nowrap-first th:first-child, .ga-table--nowrap-first td:first-child { white-space: nowrap; }
.ga-table .ga-num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── Tabs ───────────────────────────────────────────────────────────────── */
.ga-tabs {
    display: flex;
    gap: var(--ga-space-1);
    margin: 0 0 var(--ga-space-4);
    overflow-x: auto;
    border-bottom: var(--ga-border-w) solid var(--ga-line);
}
.ga-tab {
    display: inline-flex;
    align-items: center;
    min-height: var(--ga-tap-min);
    padding: 0 var(--ga-space-4);
    margin-bottom: calc(-1 * var(--ga-border-w));
    border-bottom: var(--ga-border-w-strong) solid transparent;
    color: var(--ga-text-muted);
    font-size: var(--ga-text-md);
    text-decoration: none;
    white-space: nowrap;
}
.ga-tab:hover, .ga-tab:focus { background: var(--ga-surface-sunken); color: var(--ga-text); text-decoration: none; }
.ga-tab:focus-visible { outline: none; box-shadow: var(--ga-focus-ring); }
.ga-tab[aria-selected="true"], .ga-tab[aria-current="page"] {
    border-bottom-color: var(--ga-accent);
    color: var(--ga-accent);
    font-weight: var(--ga-weight-bold);
}

/* ── Form field ─────────────────────────────────────────────────────────── */
.ga-field { display: flex; flex-direction: column; gap: var(--ga-space-1); margin: 0 0 var(--ga-space-3); }
.ga-field > label, .ga-label {
    display: block;
    margin: 0;
    color: var(--ga-text);
    font-size: var(--ga-text-sm);
    font-weight: var(--ga-weight-semibold);
    line-height: var(--ga-leading);
}
.ga-input, input.ga-input, select.ga-input, textarea.ga-input {
    box-sizing: border-box;
    display: block;
    width: 100%;
    max-width: 100%;
    height: auto;
    min-height: var(--ga-tap-min);
    margin: 0;
    padding: var(--ga-space-2) var(--ga-space-3);
    border: var(--ga-border-w) solid var(--ga-line-strong);
    border-radius: var(--ga-radius-sm);
    background: var(--ga-surface);
    color: var(--ga-text);
    font-family: inherit;
    font-size: var(--ga-text-md);
    line-height: var(--ga-leading);
    box-shadow: none;
    transition: none;
}
textarea.ga-input { min-height: calc(var(--ga-tap-min) * 2); resize: vertical; }
.ga-input:focus, input.ga-input:focus, select.ga-input:focus, textarea.ga-input:focus {
    outline: none;
    border-color: var(--ga-accent);
    box-shadow: var(--ga-focus-ring);
}
.ga-input.is-invalid, input.ga-input.is-invalid, select.ga-input.is-invalid, textarea.ga-input.is-invalid { border-color: var(--ga-bad); }
.ga-input[disabled], input.ga-input[disabled], select.ga-input[disabled], textarea.ga-input[disabled] { background: var(--ga-surface-sunken); color: var(--ga-text-muted); cursor: not-allowed; }
.ga-field__help { margin: 0; color: var(--ga-text-muted); font-size: var(--ga-text-xs); }
.ga-field__error { margin: 0; color: var(--ga-bad); font-size: var(--ga-text-sm); font-weight: var(--ga-weight-semibold); }
.ga-check { display: flex; align-items: flex-start; gap: var(--ga-space-2); min-height: var(--ga-tap-min); padding: var(--ga-space-2) 0; }
.ga-check input[type="checkbox"], .ga-check input[type="radio"] {
    flex: none;
    width: var(--ga-size-check);
    height: var(--ga-size-check);
    margin: 0;
    accent-color: var(--ga-accent);
}
.ga-check label { display: block; margin: 0; color: var(--ga-text); font-size: var(--ga-text-md); line-height: var(--ga-leading); }

/* ── Tile: an attachment (PDF, Markdown, HTML, office documents) ──────────────────────────── */
.ga-tile {
    position: relative;
    box-sizing: border-box;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ga-space-1);
    width: var(--ga-size-tile);
    padding: var(--ga-space-2) var(--ga-space-1);
    border-radius: var(--ga-radius-md);
    color: var(--ga-text);
    text-decoration: none;
}
.ga-tile:hover, .ga-tile:focus { background: var(--ga-surface-sunken); color: var(--ga-text); text-decoration: none; }
.ga-tile:focus-visible { outline: none; box-shadow: var(--ga-focus-ring); }
.ga-tile__icon {
    box-sizing: border-box;
    display: flex;
    align-items: flex-end;
    width: var(--ga-size-tile-icon);
    height: var(--ga-size-tile-icon);
    overflow: hidden;
    border: var(--ga-border-w-strong) solid var(--ga-tile-color, var(--ga-file-other));
    border-radius: var(--ga-radius-sm);
    background: var(--ga-surface);
}
.ga-tile__type {
    display: block;
    width: 100%;
    padding: var(--ga-space-0) 0;
    background: var(--ga-tile-color, var(--ga-file-other));
    color: var(--ga-text-inverse);
    font-size: var(--ga-text-xs);
    font-weight: var(--ga-weight-bold);
    line-height: var(--ga-leading-tight);
    text-align: center;
}
.ga-tile__name {
    max-width: 100%;
    overflow: hidden;
    font-size: var(--ga-text-xs);
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ga-tile__dot {
    position: absolute;
    top: var(--ga-space-1);
    right: var(--ga-space-3);
    width: var(--ga-size-dot);
    height: var(--ga-size-dot);
    box-sizing: border-box;
    border: var(--ga-border-w-strong) solid var(--ga-surface);
    border-radius: var(--ga-radius-round);
    background: var(--ga-notify);
}
.ga-tile--pdf { --ga-tile-color: var(--ga-file-pdf); }
.ga-tile--md { --ga-tile-color: var(--ga-file-md); }
.ga-tile--html { --ga-tile-color: var(--ga-file-html); }
/* office documents: word-processing, spreadsheet, presentation, plain text (download-only) */
.ga-tile--word { --ga-tile-color: var(--ga-file-word); }
.ga-tile--sheet { --ga-tile-color: var(--ga-file-sheet); }
.ga-tile--slides { --ga-tile-color: var(--ga-file-slides); }
.ga-tile--text { --ga-tile-color: var(--ga-file-text); }

/* ── List: rows "text, meta, action" (goals, files) ─────────────────────── */
.ga-list { margin: 0; padding: 0; list-style: none; }
.ga-list__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ga-space-3);
    min-height: var(--ga-tap-min);
    padding: var(--ga-space-2) 0;
    border-bottom: var(--ga-border-w) solid var(--ga-line);
}
.ga-list__item:last-child { border-bottom: 0; }
.ga-list__main { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.ga-list__hint { display: block; color: var(--ga-text-muted); font-size: var(--ga-text-xs); }
.ga-list__meta { flex: none; color: var(--ga-text-muted); font-size: var(--ga-text-sm); }

/* ── Progress ───────────────────────────────────────────────────────────── */
.ga-progress {
    -webkit-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    height: var(--ga-size-bar);
    border: 0;
    border-radius: var(--ga-radius-pill);
    background: var(--ga-line);
    color: var(--ga-accent);
    overflow: hidden;
}
.ga-progress::-webkit-progress-bar { background: var(--ga-line); }
.ga-progress::-webkit-progress-value { background: var(--ga-accent); }
.ga-progress::-moz-progress-bar { background: var(--ga-accent); }
.ga-progress--ok { color: var(--ga-ok); }
.ga-progress--ok::-webkit-progress-value { background: var(--ga-ok); }
.ga-progress--ok::-moz-progress-bar { background: var(--ga-ok); }

/* ── Reaction: emoji with a counter under a post ────────────────────────── */
.ga-reaction {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    gap: var(--ga-space-1);
    min-height: var(--ga-tap-compact);
    margin: 0;
    padding: var(--ga-space-1) var(--ga-space-3);
    border: var(--ga-border-w) solid var(--ga-line);
    border-radius: var(--ga-radius-pill);
    background: var(--ga-surface-sunken);
    color: var(--ga-text);
    font-family: inherit;
    font-size: var(--ga-text-md);
    line-height: var(--ga-leading-tight);
    text-decoration: none;
    cursor: pointer;
}
.ga-reaction:hover, .ga-reaction:focus { background: var(--ga-surface-hover); color: var(--ga-text); text-decoration: none; }
.ga-reaction:focus-visible { outline: none; box-shadow: var(--ga-focus-ring); }
.ga-reaction.is-active { background: var(--ga-accent-soft); border-color: var(--ga-accent-line); }
.ga-reaction.is-active:hover, .ga-reaction.is-active:focus { background: var(--ga-accent-soft-hover); }
.ga-reaction__count { color: var(--ga-text-muted); font-size: var(--ga-text-xs); }
@media (pointer: coarse) {
    .ga-reaction { min-height: var(--ga-tap-min); }
}

/* ── FAB: round action button on a phone ────────────────────────────────── */
.ga-fab {
    position: fixed;
    right: var(--ga-space-4);
    bottom: var(--ga-fab-bottom);
    z-index: var(--ga-z-fab);
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--ga-size-fab);
    height: var(--ga-size-fab);
    border: 0;
    border-radius: var(--ga-radius-round);
    background: var(--ga-ok);
    color: var(--ga-text-inverse);
    font-size: var(--ga-text-display);
    line-height: 1;
    text-decoration: none;
    box-shadow: var(--ga-shadow-md);
    cursor: pointer;
}
.ga-fab:hover, .ga-fab:focus { background: var(--ga-text); color: var(--ga-text-inverse); text-decoration: none; }
.ga-fab:focus-visible { outline: none; box-shadow: var(--ga-focus-ring); }
.ga-fab--static { position: static; }

/* ── Overlay and window: the reader chrome, any modal ───────────────────── */
.ga-overlay {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: var(--ga-z-overlay);
    box-sizing: border-box;
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--ga-space-5);
    background: var(--ga-backdrop);
}
.ga-overlay.is-open { display: flex; }
.ga-overlay--inline { position: relative; z-index: auto; min-height: var(--ga-size-preview); padding: var(--ga-space-4); }
.ga-window {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    width: var(--ga-size-window);
    max-width: 100%;
    max-height: 100%;
    overflow: hidden;
    border-radius: var(--ga-radius-md);
    background: var(--ga-surface);
    color: var(--ga-text);
    box-shadow: var(--ga-shadow-lg);
}
.ga-window__head {
    flex: none;
    display: flex;
    align-items: center;
    gap: var(--ga-space-3);
    padding: var(--ga-space-2) var(--ga-space-3);
    border-bottom: var(--ga-border-w) solid var(--ga-line);
    background: var(--ga-surface-sunken);
}
.ga-window__title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    font-weight: var(--ga-weight-bold);
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ga-window__body { flex: 1 1 auto; overflow-y: auto; padding: var(--ga-space-4) var(--ga-space-5); }
@media (max-width: 767px) {
    .ga-overlay:not(.ga-overlay--inline) { padding: 0; }
    .ga-overlay:not(.ga-overlay--inline) .ga-window { width: 100%; height: 100%; border-radius: 0; }
}

/* ── Photo viewer: full-screen picture with zoom, swipe and a counter ───── */
/* Shell is .ga-overlay.ga-overlay--viewer (opaque, edge to edge); the pieces live in .ga-viewer.
   Behaviour: assets/app/photo_viewer.js (marker contract in docs/ARCHITECTURE.md). */
.ga-overlay--viewer { padding: 0; background: var(--ga-viewer-bg); color: var(--ga-text-inverse); touch-action: none; overscroll-behavior: contain; }
.ga-overlay--viewer.ga-overlay--inline { padding: 0; min-height: 0; }
.ga-viewer {
    position: relative;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow: hidden;
    color: var(--ga-text-inverse);
    font-size: var(--ga-text-md);
    line-height: var(--ga-leading);
}
.ga-overlay--inline .ga-viewer { height: var(--ga-size-preview); }
.ga-viewer__stage {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    touch-action: none;
    cursor: zoom-in;
    -webkit-user-select: none;
    user-select: none;
}
.ga-viewer__stage.is-zoomed { cursor: grab; }
.ga-viewer__stage.is-dragging { cursor: grabbing; }
.ga-viewer__img {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: scale-down;
    image-orientation: from-image;
    transform-origin: 50% 50%;
    will-change: transform;
    -webkit-user-drag: none;
    user-select: none;
}
.ga-viewer__img.is-animated { transition: transform var(--ga-duration) ease-out; }
.ga-viewer__img.is-hidden { visibility: hidden; }
.ga-viewer__bar {
    flex: none;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: var(--ga-space-2);
    padding: var(--ga-space-2) var(--ga-space-3);
    padding-left: max(var(--ga-space-3), env(safe-area-inset-left));
    padding-right: max(var(--ga-space-3), env(safe-area-inset-right));
}
.ga-viewer__bar--top { padding-top: max(var(--ga-space-2), env(safe-area-inset-top)); }
.ga-viewer__bar--bottom { justify-content: center; padding-bottom: max(var(--ga-space-2), env(safe-area-inset-bottom)); }
.ga-viewer__bar[hidden] { display: none; }
.ga-viewer__spacer { flex: 1 1 auto; }
.ga-viewer [hidden] { display: none; }
.ga-viewer__btn {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--ga-tap-min);
    min-height: var(--ga-tap-min);
    padding: 0 var(--ga-space-3);
    border: 0;
    border-radius: var(--ga-radius-pill);
    background: var(--ga-viewer-chrome);
    color: var(--ga-text-inverse);
    font: inherit;
    font-size: var(--ga-text-lg);
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
}
.ga-viewer__btn:hover, .ga-viewer__btn:focus { background: var(--ga-text-muted); color: var(--ga-text-inverse); text-decoration: none; }
.ga-viewer__btn:focus-visible { outline: var(--ga-border-w-strong) solid var(--ga-text-inverse); outline-offset: var(--ga-space-0); }
.ga-viewer__btn[disabled] { cursor: default; background: var(--ga-viewer-chrome); opacity: var(--ga-opacity-disabled); }
.ga-viewer__btn--prev, .ga-viewer__btn--next { position: absolute; top: 50%; z-index: 1; margin-top: calc(var(--ga-tap-min) / -2); }
.ga-viewer__btn--prev { left: max(var(--ga-space-3), env(safe-area-inset-left)); }
.ga-viewer__btn--next { right: max(var(--ga-space-3), env(safe-area-inset-right)); }
.ga-viewer__counter, .ga-viewer__caption {
    box-sizing: border-box;
    max-width: 100%;
    padding: var(--ga-space-1) var(--ga-space-3);
    border-radius: var(--ga-radius-pill);
    background: var(--ga-viewer-chrome);
    color: var(--ga-text-inverse);
    font-size: var(--ga-text-sm);
}
.ga-viewer__caption { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ga-viewer__status {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 1;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ga-space-3);
    max-width: 90%;
    padding: var(--ga-space-4);
    border-radius: var(--ga-radius-md);
    background: var(--ga-viewer-chrome);
    color: var(--ga-text-inverse);
    text-align: center;
    transform: translate(-50%, -50%);
}
.ga-viewer__status[hidden] { display: none; }
.ga-viewer__status a { color: var(--ga-text-inverse); text-decoration: underline; }
@media (hover: none) {
    .ga-viewer__btn--prev, .ga-viewer__btn--next { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    .ga-viewer__img.is-animated { transition: none; }
}

/* ── Heat map: activity cells ───────────────────────────────────────────── */
.ga-heat { width: 100%; margin: 0; border-collapse: collapse; font-size: var(--ga-text-sm); color: var(--ga-text); }
.ga-heat th { padding: var(--ga-space-1); color: var(--ga-text-muted); font-size: var(--ga-text-xs); font-weight: var(--ga-weight-regular); text-align: center; white-space: nowrap; }
.ga-heat__cell { padding: var(--ga-space-1) var(--ga-space-2); border: var(--ga-border-w) solid var(--ga-line); background: var(--ga-surface); text-align: center; }
.ga-heat__cell--weekend { background: var(--ga-heat-weekend); }
.ga-heat__cell--l1 { background: var(--ga-accent-soft); }
.ga-heat__cell--l2 { background: var(--ga-accent-soft-hover); }
.ga-heat__cell--l3 { background: var(--ga-accent-line); }

/* ── Status slot: a save/progress indicator that never moves the layout ─────
 * The box is reserved from the first paint (tap-min square, flex: none); the
 * states --saving / --saved / --error change only what is DRAWN inside it, with
 * opacity and visibility, never display or size. Words go to the one
 * .ga-status__text live region (visually hidden); the error mark is a button
 * that retries. */
.ga-status {
    position: relative;
    box-sizing: border-box;
    flex: none;
    width: var(--ga-tap-min);
    height: var(--ga-tap-min);
    overflow: hidden;
    font-size: var(--ga-text-md);
    font-weight: var(--ga-weight-bold);
    line-height: 1;
    white-space: nowrap;
}
.ga-status__mark, .ga-status__retry {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: var(--ga-opacity-hidden);
    transition: opacity var(--ga-duration);
    pointer-events: none;
}
.ga-status__mark--saving { color: var(--ga-text-muted); }
.ga-status__mark--saved { color: var(--ga-ok); }
.ga-status__retry {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    border: var(--ga-border-w-strong) solid var(--ga-bad-line);
    border-radius: var(--ga-radius-round);
    background: var(--ga-bad-soft);
    color: var(--ga-bad);
    font: inherit;
    cursor: pointer;
    visibility: hidden;
}
.ga-status__retry:focus-visible { outline: var(--ga-border-w-strong) solid var(--ga-accent); outline-offset: calc(-1 * var(--ga-border-w-strong)); }
.ga-status--saving .ga-status__mark--saving,
.ga-status--saved .ga-status__mark--saved { opacity: var(--ga-opacity-shown); }
.ga-status--error .ga-status__retry { opacity: var(--ga-opacity-shown); visibility: visible; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) {
    .ga-status__mark, .ga-status__retry { transition: none; }
}

/* ── BEGIN busy state: ga-spinner, ga-btn.is-busy ───────────────────────────
   A button that is working keeps its exact box: the label stays in the flow
   (visibility: hidden keeps its width and height) and the spinner is laid over
   it, centred, out of the flow. Nothing around the button can move. */
.ga-btn { position: relative; }
.ga-spinner {
    display: inline-block;
    box-sizing: border-box;
    width: var(--ga-size-spinner);
    height: var(--ga-size-spinner);
    border: var(--ga-border-w-strong) solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: ga-spin var(--ga-spinner-duration) linear infinite;
}
.ga-btn > .ga-spinner {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: calc(var(--ga-size-spinner) / -2);
    margin-left: calc(var(--ga-size-spinner) / -2);
    visibility: hidden;
}
.ga-alert[hidden] { display: none; }
.ga-btn.is-busy { cursor: progress; }
.ga-btn.is-busy[disabled] { opacity: unset; }
.ga-btn.is-busy > .ga-btn__label { visibility: hidden; }
.ga-btn.is-busy > .ga-spinner { visibility: visible; }
@keyframes ga-spin {
    to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .ga-spinner { animation: none; border-color: transparent; line-height: var(--ga-size-spinner); text-align: center; }
    .ga-spinner::after { content: "\2026"; }
}
/* ── END busy state ─────────────────────────────────────────────────────── */

/* ── BEGIN goal albums: album choice for inbox photos ───────────────────── */
.ga-album-choice {
    box-sizing: border-box;
    min-width: 0;
    margin: var(--ga-space-3) 0 0;
    padding: var(--ga-space-3);
    border: var(--ga-border-w) solid var(--ga-accent-line);
    border-radius: var(--ga-radius-md);
    background: var(--ga-accent-soft);
    color: var(--ga-text);
}
.ga-album-choice[hidden], .ga-album-choice__new[hidden] { display: none; }
.ga-album-choice__legend {
    display: block;
    width: auto;
    margin: 0;
    padding: 0 var(--ga-space-1);
    border: 0;
    color: var(--ga-text);
    font-size: var(--ga-text-sm);
    font-weight: var(--ga-weight-semibold);
    line-height: var(--ga-leading);
}
.ga-album-choice .ga-field:last-child { margin-bottom: 0; }
/* ── END goal albums ────────────────────────────────────────────────────── */
