/* ============================================================
   Components — reusable, token-driven functional classes.
   Prefer these (and Bootstrap utilities) over ad-hoc CSS.
   Everything here reads from tokens.css, so re-theming never
   requires touching this file.
   ============================================================ */

/* ════════════════════════════════════════════════════════════
   Navigation — a light, sticky, near-weightless top bar.
   ════════════════════════════════════════════════════════════ */
.app-navbar {
    /* Size the bar with vertical padding (not min-height): the brand keeps the
       same top padding whether the mobile menu is collapsed or expanded, so
       opening the menu no longer makes the logo/toggler jump upward. */
    --bs-navbar-padding-y: 1rem;
    background-color: rgba(255, 255, 255, 0.8);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--border-subtle);
}

.app-brand {
    font-weight: 650;
    font-size: var(--text-lg);
    letter-spacing: var(--tracking-tight);
    color: var(--ink);
}
.app-brand:hover {
    color: var(--ink);
}
.app-brand .app-brand__mark {
    font-size: 1.35rem;
    line-height: 1;
}

/* Nav links: quiet by default, a soft pill on hover, ink when active. */
.app-navbar .nav-link {
    --bs-nav-link-padding-x: 0.85rem;
    --bs-nav-link-padding-y: 0.5rem;
    position: relative;
    font-size: var(--text-sm);
    font-weight: 550;
    color: var(--neutral-500);
    border-radius: var(--radius-sm);
    transition: color var(--ease), background-color var(--ease);
}
.app-navbar .nav-link:hover,
.app-navbar .nav-link:focus-visible {
    color: var(--ink);
    background-color: var(--surface-muted);
}
.app-navbar .nav-link.active {
    color: var(--ink);
    font-weight: 600;
}
/* Accent underline indicator on the active item (lg+). */
/* ≥ lg — breakpoint token --bp-lg (992px) */
@media (min-width: 992px) {
    .app-navbar .nav-link.active::after {
        content: "";
        position: absolute;
        left: 0.85rem;
        right: 0.85rem;
        bottom: -1px;
        height: 2px;
        border-radius: var(--radius-pill);
        background: var(--accent);
    }
}

/* Compact ghost buttons in the navbar (locale switch, logout). */
.app-navbar .navbar-toggler {
    border: 0;
    padding: 0.25rem 0.4rem;
    color: var(--neutral-600);
}
.app-navbar .navbar-toggler:focus {
    box-shadow: var(--shadow-focus);
}

/* ── Mobile menu (below lg) — a clean, spacious stacked panel ─────────────── */
/* < lg — breakpoint token --bp-lg (992px) */
@media (max-width: 991.98px) {
    .app-navbar .navbar-collapse {
        margin-top: 0.75rem;
        padding-top: 0.25rem;
        border-top: 1px solid var(--border-subtle);
    }
    /* Comfortable, full-width tap rows. */
    .app-navbar .navbar-collapse .nav-link {
        padding: 0.65rem 0.25rem;
        font-size: var(--text-base);
    }
    .app-navbar .navbar-collapse .nav-link.active {
        color: var(--accent-emphasis);
        font-weight: 600;
    }
    /* Each cluster stacks full-width; the actions become their own sections. */
    .app-navbar .navbar-actions {
        width: 100%;
        margin-top: 0.25rem;
    }
    /* A section = a hairline-separated group with a small, quiet label. */
    .app-navbar .nav-section {
        width: 100%;
        margin-top: 0.75rem;
        padding-top: 0.75rem;
        border-top: 1px solid var(--border-subtle);
    }
    .app-navbar .nav-section__label {
        font-size: var(--text-xs);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--neutral-500);
        margin-bottom: 0.15rem;
    }
    /* Language switch sits on its own row at the very bottom. */
    .app-navbar .navbar-actions .locale-switch {
        margin-top: 0.75rem;
    }
}

/* Segmented pill control — shared by the locale switch and the checklist
   view switch, so both toggles read as the same component. */
.locale-switch,
.segmented {
    display: inline-flex;
    padding: 0.15rem;
    gap: 0.1rem;
    background: var(--surface-muted);
    border-radius: var(--radius-pill);
}
.locale-switch__item,
.segmented__item {
    display: inline-flex;
    align-items: center;
    padding: 0.5rem 0.75rem;
    font-size: var(--text-xs);
    line-height: 1;
    border-radius: var(--radius-pill);
    color: var(--neutral-500);
    transition: background-color var(--ease), color var(--ease);
}
/* Larger flag glyphs read better than the shared segmented text size. */
.locale-switch__item {
    font-size: var(--text-lg);
    padding-block: 0.35rem;
}
.locale-switch__item:hover,
.segmented__item:hover {
    color: var(--ink);
}
.locale-switch__item.is-active,
.segmented__item.is-active {
    background: var(--surface-card);
    color: var(--ink);
    box-shadow: var(--shadow-xs);
}
/* Button-based segmented items (the view switch) need a native-button reset
   plus a little room between icon and label. */
.segmented__item {
    gap: 0.35rem;
    padding-inline: 0.7rem;
    border: 0;
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
    white-space: nowrap;
}

/* ════════════════════════════════════════════════════════════
   Buttons & surfaces
   ════════════════════════════════════════════════════════════ */

/* Call-to-action — the hero action. The one place accent goes bold. */
.btn-cta {
    background: var(--accent);
    border: 0;
    color: #fff;
    font-weight: 600;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
    transition: background-color var(--ease), transform var(--ease), box-shadow var(--ease);
}
.btn-cta:hover:not(:disabled),
.btn-cta:focus-visible {
    color: #fff;
    background: var(--accent-hover);
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}
.btn-cta:active:not(:disabled) {
    transform: translateY(0);
}
.btn-cta:disabled {
    background: var(--neutral-300);
    opacity: 1;
}

/* Ghost button — a tertiary / utility action that recedes until interacted
   with (e.g. an inline view toggle). No fill or border at rest. */
.btn-ghost {
    background: transparent;
    border: 1px solid transparent;
    color: var(--neutral-600);
}
.btn-ghost:hover,
.btn-ghost:focus-visible {
    background: var(--surface-hover);
    color: var(--ink);
}

/* Subtle tinted accent surface, e.g. highlight panels. */
.surface-accent {
    background: var(--accent-subtle);
    color: var(--accent-emphasis);
}

/* ════════════════════════════════════════════════════════════
   Cards
   ════════════════════════════════════════════════════════════ */
.card-interactive {
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: box-shadow var(--ease), transform var(--ease), border-color var(--ease);
}
.card-interactive:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--border-strong);
    transform: translateY(-2px);
}

/* ════════════════════════════════════════════════════════════
   Poll / questionnaire
   ════════════════════════════════════════════════════════════ */

/* Question card header — clean, with a hairline divider. */
.poll-question-header {
    background: var(--surface-card);
    border-bottom: 1px solid var(--border-subtle);
    padding: 1rem 1.25rem;
}
.poll-question-title {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0;
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--ink);
    letter-spacing: var(--tracking-snug);
}

/* Numbered step badge — small, filled accent. */
.step-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.6rem;
    height: 1.6rem;
    font-size: var(--text-xs);
    font-weight: 700;
    color: #fff;
    border-radius: var(--radius-pill);
    background: var(--accent);
}

/* Answers flow in a uniform responsive grid; every tile is the same size.
   Follow-ups are NOT nested in a tile — they render as full-width sub-cards
   after the grid, so tiles stay homogeneous. */
.poll-options {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr));
    gap: 0.5rem;
}

/* Selectable answer — a fully-clickable <label> tile (wraps its checkbox, so a
   click anywhere toggles it) that reacts on hover/checked. */
.poll-option {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.7rem 0.9rem;
    margin: 0;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-card);
    cursor: pointer;
    transition: border-color var(--ease), background-color var(--ease), box-shadow var(--ease);
}
.poll-option .form-check-input {
    margin: 0;
    flex-shrink: 0;
    cursor: pointer;
}
.poll-option__label {
    cursor: pointer;
    color: var(--neutral-700);
    line-height: 1.3;
}
.poll-option:hover {
    border-color: var(--border-strong);
    background: var(--surface-sunken);
}
.poll-option:has(.form-check-input:checked) {
    border-color: var(--accent);
    background: var(--accent-subtle);
    box-shadow: inset 0 0 0 1px var(--accent);
}
.poll-option:has(.form-check-input:checked) .poll-option__label {
    font-weight: 600;
    color: var(--accent-emphasis);
}

/* Branching answer — a chevron hints it opens a follow-up, flips when selected. */
.poll-option--branch::after {
    content: "";
    margin-left: auto;
    width: 0.5em;
    height: 0.5em;
    border-right: 2px solid var(--neutral-400);
    border-bottom: 2px solid var(--neutral-400);
    transform: rotate(45deg);
    transition: transform var(--ease), border-color var(--ease);
    flex-shrink: 0;
}
.poll-option--branch:has(.form-check-input:checked)::after {
    border-color: var(--accent);
    transform: rotate(225deg);
}

/* Nested follow-up — an indented, tinted sub-panel. */
.poll-subquestion {
    margin-top: 0.6rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--accent-border);
    border-left-width: 3px;
    border-radius: var(--radius-md);
    background: var(--accent-subtle);
}
.poll-sub-header {
    margin: 0 0 0.6rem;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--accent-emphasis);
}
.poll-followup:not(.d-none) {
    animation: poll-reveal 0.2s ease;
}
@keyframes poll-reveal {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}

/* Unanswered visible question flagged on submit. */
.poll-question--invalid {
    box-shadow: 0 0 0 2px var(--danger);
    border-radius: var(--radius-lg);
}

/* ════════════════════════════════════════════════════════════
   Progress bar
   ════════════════════════════════════════════════════════════ */
.progress-bar-wrapper {
    transition: opacity var(--ease-slow);
    padding: 0.5rem 0;
}
.progress-fixed {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 1050;
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-top: 1px solid var(--border-subtle);
    padding: 0.6rem 1rem;
}
.progress-track {
    height: 0.5rem;
    background: var(--surface-muted);
}
.progress-track .progress-bar {
    width: 0;
    background: var(--accent);
    transition: width var(--ease-slow);
}
.progress-readout {
    min-width: 130px;
    color: var(--neutral-600);
}

/* ════════════════════════════════════════════════════════════
   Checklist
   ════════════════════════════════════════════════════════════ */
.checklist-accordion .accordion-item {
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
}
.checklist-accordion .accordion-button {
    border-radius: var(--radius-lg);
    color: var(--ink);
    font-weight: 600;
}
.checklist-accordion .accordion-button:not(.collapsed) {
    color: var(--ink);
    background: var(--surface-card);
    box-shadow: none;
}
.checklist-accordion .accordion-button:focus {
    box-shadow: var(--shadow-focus);
}
.checklist-accordion .accordion-button::after {
    width: 1rem;
    height: 1rem;
    background-size: 1rem;
}

/* Gear rows. */
.gear-item {
    border-left: 3px solid transparent;
    transition: background-color var(--ease), opacity var(--ease-slow), max-height var(--ease-slow);
}
.gear-item:hover {
    background-color: var(--surface-sunken);
}
.gear-item .form-check-label {
    color: var(--neutral-700);
    cursor: pointer;
    transition: color var(--ease);
}
.gear-item--checked {
    background-color: var(--accent-subtle);
    border-left-color: var(--accent);
}
.gear-item--checked .form-check-label {
    color: var(--accent-emphasis);
    font-weight: 550;
    text-decoration: line-through;
    text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.gear-item .form-check-input:checked {
    background-color: var(--accent);
    border-color: var(--accent);
}
/* Removal animation is class-driven (no inline styles from JS). */
.gear-item--removing {
    opacity: 0;
    max-height: 0 !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    overflow: hidden;
}

.gear-delete-btn {
    opacity: 0;
    transition: opacity var(--ease);
}
.gear-item:hover .gear-delete-btn,
.gear-item:focus-within .gear-delete-btn {
    opacity: 1;
}
@media (hover: none) {
    .gear-delete-btn {
        opacity: 0.6;
    }
}

/* ════════════════════════════════════════════════════════════
   Category tree widget (admin form)
   ════════════════════════════════════════════════════════════ */
.category-l1-header {
    background-color: var(--surface-muted);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    cursor: pointer;
    user-select: none;
    transition: background-color var(--ease);
}
.category-l1-header:hover {
    background-color: var(--neutral-150);
}
.category-l2-panel {
    border-left: 2px solid var(--border-default);
    margin-left: 0.3em;
}
/* Leaf rows (no children): same padding/rounding as a branch header but a
   lighter, unfilled border so dropdowns still read as the primary elements. */
.category-leaf {
    border: 1px solid var(--border-subtle);
}
.category-leaf .form-check {
    margin-bottom: 0;
}
/* Reserves the chevron's width so a leaf's checkbox lines up with a branch's. */
.category-chevron-spacer {
    display: inline-block;
    width: 0.55em;
    flex-shrink: 0;
}
.category-chevron {
    display: inline-block;
    width: 0.55em;
    height: 0.55em;
    border-right: 2px solid var(--neutral-500);
    border-bottom: 2px solid var(--neutral-500);
    transform: rotate(-45deg);
    transition: transform var(--ease);
    flex-shrink: 0;
}
.category-chevron.open,
[aria-expanded="true"] .category-chevron {
    transform: rotate(45deg);
}

/* Pagination: wrap onto centered rows on narrow viewports instead of
   overflowing the page width. */
.pagination {
    flex-wrap: wrap;
    justify-content: center;
    row-gap: 0.25rem;
}

/* Centered, comfortable reading column for focused flows (the poll). */
.content-narrow {
    max-width: 760px;
    margin-inline: auto;
}

/* ════════════════════════════════════════════════════════════
   Empty state — calm, centered, used across index/list pages.
   ════════════════════════════════════════════════════════════ */
.empty-state {
    text-align: center;
    color: var(--neutral-500);
    padding: 3rem 1rem;
}
.empty-state__icon {
    font-size: 2rem;
    opacity: 0.6;
    margin-bottom: 0.5rem;
}

/* ════════════════════════════════════════════════════════════
   Data viz — analytics charts (Chart.js via chart_controller.js).
   Ink and grid are read by the controller through getComputedStyle;
   the app is light-only, so no dark-mode overrides here (they would
   mismatch the light surface).
   ════════════════════════════════════════════════════════════ */
:root {
    --viz-text: var(--neutral-500);
    --viz-grid: var(--neutral-200);
}

/* Fixed-height responsive canvas box; Chart.js fills it. */
.viz-chart {
    position: relative;
    width: 100%;
    height: 260px;
}
.viz-chart--tall {
    height: 340px;
}
