/* One class per UI pattern. If markup is about to be copied between
   components, extract a component and a class here instead. */

/* --- App shell: full-width top bar, left sidebar beneath it (desktop),
   mobile tab bar --- */

.hc-shell {
    --hc-topbar-h: 59px; /* 58px inner + 1px border, the sidebar sticks below it */
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.hc-shell-row {
    display: flex;
    flex: 1;
    min-width: 0;
}

.hc-sidebar {
    position: sticky;
    top: var(--hc-topbar-h);
    height: calc(100vh - var(--hc-topbar-h));
    width: 232px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    padding: var(--hc-space-4) var(--hc-space-3);
    background-color: var(--hc-surface);
    border-right: 1px solid var(--hc-border-subtle);
    overflow-y: auto;
}

.hc-topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    background-color: var(--hc-topbar-bg);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--hc-border-subtle);
    /* With viewport-fit=cover the page runs under the notch when the browser
       chrome is out of the way; the frosted bar absorbs that area instead of
       letting content slide beneath the clock. Zero whenever irrelevant. */
    padding-top: env(safe-area-inset-top);
}

.hc-topbar-inner {
    display: flex;
    align-items: center;
    gap: var(--hc-space-4);
    height: 58px;
    padding: 0 var(--hc-space-5);
}

/* The homehogs wordmark: always lowercase, always pink, DejaVu Sans Bold. */
.hc-brand {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    font-family: "DejaVu Sans", sans-serif;
    font-size: var(--hc-font-size-lg);
    font-weight: 700;
    color: var(--hc-brand);
    text-transform: lowercase;
    white-space: nowrap;
}

.hc-brand:hover {
    color: var(--hc-brand);
    text-decoration: none;
}

.hc-brand i {
    color: var(--hc-accent);
}

.hc-brand-logo {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
}

.hc-nav {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

/* Section heading in the sidebar ("Letting", "The property"), only used by
   landlord households: it is what makes the letting tools read as a set
   rather than four links that happen to sit near each other. */
.hc-nav-group,
.hc-menu-group {
    padding: var(--hc-space-4) var(--hc-space-3) var(--hc-space-1);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--hc-text-muted);
}

/* The first heading sits under Home, so it needs no extra air above. */
.hc-nav-group:first-child {
    padding-top: 0;
}

.hc-nav-link {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    padding: 12px var(--hc-space-3);
    border-radius: var(--hc-radius-sm);
    color: var(--hc-text-muted);
    font-size: var(--hc-font-size-base);
    font-weight: 550;
    white-space: nowrap;
}

.hc-nav-link i {
    width: 24px;
    text-align: center;
    font-size: 17px;
}

.hc-nav-link:hover {
    color: var(--hc-text);
    background-color: var(--hc-accent-soft);
    text-decoration: none;
}

.hc-nav-link.active {
    color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
}

.hc-topbar-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    /* The whole chain down to the home-switcher select must be allowed to
       shrink, or on narrow phones the row holds its content width and pushes
       the page into horizontal scroll. Only the switcher pill gives way (its
       select ellipsises what no longer fits); the ring, bell and avatar keep
       their fixed sizes. */
    min-width: 0;
}

.hc-topbar-actions > * {
    flex: none;
}

.hc-topbar-actions > .hc-context-switch {
    flex: 0 1 auto;
    min-width: 0;
}

.hc-topbar-actions .hc-context-switch select {
    min-width: 0;
}

.hc-main {
    flex: 1;
    width: 100%;
    min-width: 0;
    max-width: 1100px;
    margin: 0 auto;
    /* The bottom is 96px, not a space token, because the chat bubble is fixed
       to the viewport at 20px + 56px tall. Anything less and the last control
       on a short page sits under the pig, which is exactly where a "See
       everything" or a "Save" button tends to end up. Mobile already does
       this for the tab bar. */
    padding: var(--hc-space-6) var(--hc-space-5) 96px;
}

/* Mobile: bottom tab bar (Instagram-style); profile lives in the tab bar. */
.hc-tabbar {
    display: none;
}

@media (max-width: 960px) {
    .hc-sidebar {
        display: none;
    }

    /* The avatar moves into the tab bar as the Profile tab on mobile. */
    .hc-topbar-user {
        display: none;
    }

    .hc-main {
        /* Room for the floating glass bar plus its 10px hover gap. */
        padding: var(--hc-space-4) var(--hc-space-4) calc(96px + env(safe-area-inset-bottom));
    }

    /* Narrow phones: the logo alone marks the brand, the text would push the
       XP ring, home switcher and bell off the edge. */
    @media (max-width: 640px) {
        .hc-topbar .hc-brand span {
            display: none;
        }

        .hc-context-switch select {
            max-width: 120px;
        }
    }

    /* No fade element behind the bar: iOS Safari repaints fixed layers
       unreliably while its toolbars animate, and every variant (overdraw,
       viewport-fit=cover) still showed a moving edge on device. The frosted
       pill carries the depth on its own. Do not reintroduce a bottom veil
       without testing the Safari toolbar transition on a real iPhone. */

    /* The floating pill, now SOLID: the frosted translucent version's
       backdrop blur was the "gradient behind the bar" that iOS Safari kept
       mangling during toolbar transitions, so glass is retired for good on
       this element (see the veil note above for the same lesson). A clean
       surface with a modest shadow floats just as well and glitches never.
       Safe-area keeps it clear of the home indicator in both toolbar
       states now viewport-fit=cover makes the inset real. */
    .hc-tabbar {
        display: flex;
        position: fixed;
        left: 14px;
        right: 14px;
        bottom: calc(8px + env(safe-area-inset-bottom));
        z-index: 50;
        justify-content: space-around;
        align-items: center;
        gap: 4px;
        padding: 8px 10px;
        border-radius: var(--hc-radius-full);
        background-color: var(--hc-surface);
        border: 1px solid var(--hc-border-subtle);
        box-shadow: var(--hc-shadow);
    }

    /* Icon-only tabs, Instagram-style: each takes an equal share of the
       pill, so every tab's active bubble is the same wide oval. Raised above
       the sliding indicator so icons always paint over it. */
    .hc-tab {
        display: flex;
        position: relative;
        z-index: 1;
        flex: 1 1 0;
        align-items: center;
        justify-content: center;
        max-width: 88px;
        padding: 11px 0;
        border-radius: var(--hc-radius-full);
        color: var(--hc-text-muted);
    }

    .hc-tab i {
        font-size: 1.3rem;
    }

    .hc-tab:hover {
        text-decoration: none;
        color: var(--hc-text);
    }

    .hc-tab.active {
        color: var(--hc-text);
    }

    .hc-tab.active i {
        color: var(--hc-accent);
    }

    /* The current tab's bubble is ONE element, slid under whichever tab is
       active (tabbar.js sets width and translateX), so changing page glides
       the bubble across the bar. Landing on a page with no tab pops it in
       instead: the -on class fades and scales it up while the js places it
       with transitions suppressed. The overshoot curve is the "cool". */
    .hc-tab-indicator {
        position: absolute;
        top: 8px;
        bottom: 8px;
        left: 0;
        width: 0;
        border-radius: var(--hc-radius-full);
        background-color: var(--hc-tab-active-bg);
        box-shadow: var(--hc-tab-active-shadow);
        opacity: 0;
        scale: 0.5;
        pointer-events: none;
        transition:
            transform 0.3s cubic-bezier(0.3, 1.25, 0.45, 1),
            width 0.3s cubic-bezier(0.3, 1.25, 0.45, 1),
            scale 0.25s cubic-bezier(0.3, 1.25, 0.45, 1),
            opacity 0.18s ease;
    }

    .hc-tab-indicator.hc-tab-indicator-on {
        opacity: 1;
        scale: 1;
    }

    /* The topbar "+" retires on mobile: the tab bar's Add circle is the
       capture point, and the header slot goes to the account icon. Scoped
       under .hc-topbar-actions because a media query adds no specificity,
       and the base .hc-icon-btn / .hc-topbar-account rules sit later in
       this file and would win a same-specificity fight. */
    .hc-topbar-actions .hc-quickadd-btn {
        display: none;
    }

    .hc-topbar-actions .hc-topbar-account {
        display: inline-flex;
    }
}

/* --- "Coming soon" (preview features advertised in the nav) ------------
   While a feature sits behind PreviewFeatures, members see its nav item
   disabled with this pill rather than not at all: the feature is advertised
   without opening access (the page gate is untouched). Muted accent tint so
   it reads as information, not a call to action, and follows the member's
   chosen accent theme. */
.hc-soon-pill {
    align-self: center;
    padding: 3px 8px;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
    font-size: 10px;
    font-weight: 650;
    line-height: 1;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

/* The disabled item is a <span>, not a link: nothing to follow, nothing to
   focus, and the muted colour says so before anyone tries. The hover reset
   stops it borrowing the real links' "I'm clickable" highlight. */
.hc-nav-link--soon {
    cursor: default;
    opacity: 0.65;
}

.hc-nav-link--soon:hover {
    color: var(--hc-text-muted);
    background-color: transparent;
}

/* On the tab bar the pill overlays the top edge, notification-badge style,
   so the fixed-height bar and its evenly sized tabs never grow. */
.hc-tab {
    position: relative;
}

.hc-tab--soon {
    cursor: default;
    opacity: 0.6;
}

.hc-tab--soon:hover {
    color: var(--hc-text-muted);
}

.hc-soon-pill--tab {
    position: absolute;
    top: -6px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 9px;
    padding: 2px 6px;
}

/* --- Avatar + dropdown menu ----------------------------------------- */

.hc-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--hc-radius-full);
    border: 1px solid var(--hc-border-subtle);
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
    font-size: var(--hc-font-size-base);
    cursor: pointer;
}

.hc-avatar:hover {
    box-shadow: var(--hc-shadow-sm);
}

.hc-menu {
    position: relative;
}

/* <details>-based menus: hide the disclosure triangle, keep the avatar look. */
.hc-menu > summary {
    list-style: none;
}

.hc-menu > summary::-webkit-details-marker {
    display: none;
}

.hc-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 60;
}

.hc-menu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    z-index: 61;
    min-width: 220px;
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius);
    box-shadow: var(--hc-shadow-pop);
    padding: var(--hc-space-2);
}

.hc-menu-header {
    padding: var(--hc-space-2) var(--hc-space-3);
    font-size: var(--hc-font-size-xs);
    color: var(--hc-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    border-bottom: 1px solid var(--hc-border-subtle);
    margin-bottom: var(--hc-space-2);
}

.hc-menu-item {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    width: 100%;
    padding: var(--hc-space-2) var(--hc-space-3);
    border: none;
    border-radius: var(--hc-radius-sm);
    background: none;
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 500;
    text-align: left;
    cursor: pointer;
}

.hc-menu-item i {
    width: 18px;
    text-align: center;
    color: var(--hc-text-muted);
}

.hc-menu-item:hover {
    background-color: var(--hc-accent-soft);
    color: var(--hc-text);
    text-decoration: none;
}

/* --- Full-screen menu page (mobile profile tab) ---------------------- */

.hc-menu-list {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-1);
}

.hc-menu-row {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    width: 100%;
    padding: var(--hc-space-3);
    border: none;
    border-radius: var(--hc-radius-sm);
    background: none;
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-base);
    font-weight: 550;
    text-align: left;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

/* Rounded, inset highlight — hover only where hover exists, press feedback on touch. */
@media (hover: hover) {
    .hc-menu-row:hover {
        background-color: var(--hc-accent-soft);
        text-decoration: none;
        color: var(--hc-text);
    }
}

.hc-menu-row:active {
    background-color: var(--hc-accent-soft);
    text-decoration: none;
    color: var(--hc-text);
}

.hc-menu-row > i:first-child {
    width: 24px;
    text-align: center;
    color: var(--hc-accent);
}

.hc-menu-row .hc-menu-chevron {
    margin-left: auto;
    color: var(--hc-text-muted);
}

.hc-menu-row--danger,
.hc-menu-row--danger > i:first-child {
    color: var(--hc-danger);
}

/* --- Card --------------------------------------------------------- */

.hc-card {
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-lg);
    box-shadow: var(--hc-shadow-sm);
    padding: var(--hc-space-5);
    /* Long unbroken text (reference numbers, addresses, pasted answers)
       wraps inside the card instead of spilling past its edge on a phone. */
    overflow-wrap: break-word;
}

/* The one card that is allowed to shout: a permanent, unrecoverable action.
   Tinted rather than filled, so it reads as a warning and not an error that
   has already happened. */
.hc-card--danger {
    border-color: var(--hc-danger);
    background-color: var(--hc-danger-soft);
}

.hc-card--danger .hc-card-title,
.hc-card--danger .hc-card-title i {
    color: var(--hc-danger);
}

/* Standalone neighbouring buttons never touch: a horizontal gap in a row, and
   a whisper of vertical space so buttons that wrap onto a new line on a phone
   don't stack flush. Containers with their own gap (.hc-form-actions) already
   behave; this catches the ad-hoc pairs. */
.hc-card .hc-btn {
    margin-block: 2px;
}

.hc-btn + .hc-btn,
.hc-btn + .hc-icon-btn {
    margin-inline-start: var(--hc-space-2);
}

.hc-form-actions > .hc-btn + .hc-btn,
.hc-form-actions > .hc-btn + .hc-icon-btn {
    margin-inline-start: 0; /* the wrapper's gap already spaces these */
}

.hc-card--link {
    display: block;
    color: inherit;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.hc-card--link:hover {
    color: inherit;
    text-decoration: none;
    box-shadow: var(--hc-shadow);
    transform: translateY(-2px);
}

.hc-card-title {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    font-weight: 650;
    color: var(--hc-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: var(--hc-space-2);
}

.hc-card-title i {
    color: var(--hc-accent);
    font-size: var(--hc-font-size-base);
}

/* Suns stay sunny; everything else went pink with the brand. */
.hc-card-title i.fa-sun {
    color: var(--hc-highlight);
}

.hc-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--hc-space-4);
}

/* --- Buttons ------------------------------------------------------ */

.hc-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--hc-space-2);
    /* 44px is the smallest thing a thumb hits reliably, and it is the figure
       every phone platform publishes. Anything a finger taps meets it. */
    min-height: 44px;
    padding: var(--hc-space-2) var(--hc-space-4);
    border: none;
    border-radius: var(--hc-radius-sm);
    background-color: var(--hc-surface-sunken);
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    line-height: var(--hc-line-height);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s ease, transform 0.1s ease;
}

.hc-btn:hover {
    background-color: color-mix(in srgb, var(--hc-surface-sunken) 90%, var(--hc-text));
}

/* Compact variant for buttons that sit inline with text. Still 36px, which is
   as small as a tap target gets before it starts being missed; anything
   smaller belongs in a link, not a button. */
.hc-btn--sm {
    min-height: 36px;
    padding: var(--hc-space-1) var(--hc-space-3);
    font-size: var(--hc-font-size-xs);
}

/* Guided setup wizard: step trail, choice tiles, repeating rate rows. */
.hc-wizard-step--active {
    color: var(--hc-text);
    font-weight: 600;
}

.hc-choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--hc-space-2);
    margin-top: var(--hc-space-4);
}

.hc-choice {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--hc-space-2);
    min-height: 72px;
    padding: var(--hc-space-3);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius-sm);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.hc-choice:hover {
    border-color: var(--hc-accent);
}

.hc-choice--selected {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
}

.hc-rate-row {
    padding: var(--hc-space-2) 0;
    border-bottom: 1px dashed var(--hc-border);
    margin-bottom: var(--hc-space-2);
}

.hc-checkbox {
    display: inline-flex;
    align-items: center;
    gap: var(--hc-space-2);
    min-height: 36px;
}

/* Loading state, applied by app.js on click/submit. The label only fades and
   the spinner only appears after 300ms, so instant actions never flicker. */
.hc-btn--loading {
    position: relative;
    pointer-events: none;
    animation: hc-btn-label-out 0s linear 0.3s forwards;
}

@keyframes hc-btn-label-out {
    to { color: transparent; }
}

.hc-btn--loading::after {
    content: "";
    position: absolute;
    top: calc(50% - 8px);
    left: calc(50% - 8px);
    width: 16px;
    height: 16px;
    border: 2px solid var(--hc-text-muted);
    border-top-color: transparent;
    border-radius: 50%;
    opacity: 0;
    animation: hc-btn-spin 0.7s linear infinite,
               hc-btn-spinner-in 0.15s ease 0.3s forwards;
}

.hc-btn--primary.hc-btn--loading::after {
    border-color: #ffffff;
    border-top-color: transparent;
}

@keyframes hc-btn-spin {
    to { transform: rotate(360deg); }
}

@keyframes hc-btn-spinner-in {
    to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .hc-btn--loading::after {
        animation: hc-btn-spinner-in 0.15s ease 0.3s forwards;
    }
}

/* Link-styled buttons: the global a:hover accent text must not bleed
   through, it made primary buttons unreadable on hover. */
a.hc-btn:hover {
    color: var(--hc-text);
    text-decoration: none;
}

a.hc-btn--primary:hover {
    color: var(--hc-on-accent);
}

.hc-btn:active {
    transform: scale(0.97);
}

.hc-btn:focus-visible,
.hc-icon-btn:focus-visible {
    outline: 2px solid var(--hc-accent);
    outline-offset: 2px;
}

.hc-btn--primary {
    background-color: var(--hc-accent);
    color: var(--hc-on-accent);
    box-shadow: 0 1px 2px color-mix(in srgb, var(--hc-accent) 35%, transparent);
}

.hc-btn--primary:hover {
    background-color: var(--hc-accent-hover);
}

.hc-btn--block {
    display: flex;
    width: 100%;
}

.hc-btn--link {
    min-height: 0;
    border: none;
    background: none;
    padding: 0;
    color: var(--hc-accent);
    font-weight: 600;
}

.hc-btn--link:hover {
    background: none;
    color: var(--hc-accent-hover);
}

.hc-btn--danger {
    background-color: var(--hc-danger-soft);
    color: var(--hc-danger);
}

.hc-btn--danger:hover {
    background-color: color-mix(in srgb, var(--hc-danger-soft) 85%, var(--hc-danger));
}

/* Icon-only buttons for row actions (edit, delete, download). Always pair
   with title + aria-label — the icon is the only visible content. */
.hc-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: none;
    border-radius: var(--hc-radius-sm);
    background: transparent;
    color: var(--hc-text-muted);
    font-size: 15px;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
}

.hc-icon-btn:hover {
    background-color: var(--hc-surface-sunken);
    color: var(--hc-text);
}

.hc-icon-btn:active {
    transform: scale(0.94);
}

.hc-icon-btn--danger:hover {
    background-color: var(--hc-danger-soft);
    color: var(--hc-danger);
}

/* --- Badge -------------------------------------------------------- */

.hc-badge {
    display: inline-block;
    padding: var(--hc-space-1) var(--hc-space-2);
    border-radius: var(--hc-radius-full);
    font-size: var(--hc-font-size-xs);
    font-weight: 650;
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
    white-space: nowrap;
}

.hc-badge--success {
    background-color: var(--hc-success-soft);
    color: var(--hc-success);
}

.hc-badge--danger {
    background-color: var(--hc-danger-soft);
    color: var(--hc-danger);
}

.hc-badge--warning {
    background-color: var(--hc-warning-soft);
    color: var(--hc-warning);
}

/* Neutral "keep an eye on it" badge (survey monitor findings). */
.hc-badge--muted {
    background-color: var(--hc-surface-sunken, var(--hc-border-subtle));
    color: var(--hc-text-muted);
}

/* --- Expanded table detail rows (policy documents, survey findings) --- */

.hc-table-detail-row > td {
    background-color: var(--hc-surface);
}

.hc-survey-findings {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
}

.hc-survey-finding {
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-sm);
    padding: var(--hc-space-3);
}

.hc-survey-finding-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-1);
}

/* --- Quote rows (work engagement) ---------------------------------- */

.hc-quote-row {
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-sm);
    padding: var(--hc-space-3);
    margin-bottom: var(--hc-space-3);
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-1);
}

.hc-quote-row--accepted {
    border-color: var(--hc-success);
}

.hc-quote-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
}

.hc-quote-amount {
    font-weight: 700;
    margin-left: auto;
}

/* --- Forms -------------------------------------------------------- */

.hc-form-field {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-1);
    margin-bottom: var(--hc-space-4);
}

/* Column, not row. The label is already a flex row (box then text), so a lone
   checkbox looks identical either way, but a tickbox WITH a line of
   explanation under it used to lay that explanation out beside the label,
   which is what made the property form's Ownership section look scattered. */
.hc-form-field--checkbox {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--hc-space-1);
}

.hc-form-field--checkbox > p {
    margin: 0;
}

.hc-form-field--checkbox label {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    font-weight: 450;
}

/* --- Checkboxes ----------------------------------------------------
   THE checkbox: one rule for every input[type="checkbox"] in the app
   (every form is ours, so the bare element selector is safe). Context
   classes (.hc-checkbox, .hc-check-row, .hc-perm-table) only lay
   checkboxes out; the box itself is drawn once, here. The tick is an
   inline SVG data URI, not an icon font, so it paints on statically
   rendered pages before any font arrives. Data URIs cannot read CSS
   variables, so the tick colour is restated here: keep --hc-tick in
   step with --hc-on-accent (tokens.css + themes.css), which is white
   on every light-mode accent and ink on every dark-mode one. */
input[type="checkbox"] {
    --hc-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' d='M3.2 8.6l3.2 3.2 6.4-7'/%3E%3C/svg%3E");
    appearance: none;
    -webkit-appearance: none;
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--hc-border);
    border-radius: 6px;
    background-color: var(--hc-surface);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 13px 13px;
    vertical-align: -0.25em; /* beside inline label text, sit on the first line */
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

@media (prefers-color-scheme: dark) {
    input[type="checkbox"] {
        --hc-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%230f1828' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' d='M3.2 8.6l3.2 3.2 6.4-7'/%3E%3C/svg%3E");
    }
}

input[type="checkbox"]:checked {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent);
    background-image: var(--hc-tick);
}

/* Hover only where hover exists, or touch devices hold the highlight. */
@media (hover: hover) {
    input[type="checkbox"]:not(:disabled):hover {
        border-color: var(--hc-accent);
    }
}

input[type="checkbox"]:not(:disabled):active {
    transform: scale(0.92);
}

input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--hc-accent);
    outline-offset: 2px;
}

input[type="checkbox"]:disabled {
    opacity: 0.45;
    cursor: default;
}

@media (prefers-reduced-motion: reduce) {
    input[type="checkbox"] {
        transition: none;
    }

    input[type="checkbox"]:not(:disabled):active {
        transform: none;
    }
}

/* Home/property context dropdown in the top bar (only when the user belongs
   to more than one household). The form is the pill and the house icon sits
   inside it, next to the selected name. */
.hc-context-switch {
    display: inline-flex;
    align-items: center;
    gap: var(--hc-space-2);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    padding-left: 14px;
    color: var(--hc-text-muted);
}

.hc-context-switch:hover,
.hc-context-switch:focus-within {
    border-color: var(--hc-accent);
}

.hc-context-switch select {
    border: none;
    background-color: transparent;
    color: var(--hc-text);
    padding: 6px 14px 6px 0;
    font: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 550;
    cursor: pointer;
    max-width: 220px;
}

/* M365-style permission table (invite form, member access editor):
   one row per feature, View / Edit tickbox columns. */
.hc-perm-table {
    width: 100%;
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-sm);
    overflow: hidden;
    border-collapse: separate;
    border-spacing: 0;
}

.hc-perm-table th {
    text-align: left;
    font-size: var(--hc-font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--hc-text-muted);
    background: var(--hc-surface-subtle, rgba(0, 0, 0, 0.02));
    padding: var(--hc-space-2) var(--hc-space-3);
    border-bottom: 1px solid var(--hc-border-subtle);
}

.hc-perm-table td {
    padding: var(--hc-space-2) var(--hc-space-3);
    vertical-align: middle;
}

.hc-perm-table tr + tr td {
    border-top: 1px solid var(--hc-border-subtle);
}

.hc-perm-table .hc-perm-check {
    width: 64px;
    text-align: center;
}

.hc-perm-table th.hc-perm-check {
    text-align: center;
}

.hc-perm-name {
    font-weight: 550;
}

.hc-perm-name small {
    display: block;
    color: var(--hc-text-muted);
    font-weight: 400;
}

/* Checkbox look and disabled state come from the global rule above;
   the .hc-perm-check cells centre them. */

.hc-input {
    padding: var(--hc-space-2) var(--hc-space-3);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-sm);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-base);
    line-height: var(--hc-line-height);
}

/* Compact variant for inline table controls (a link's kind selector). */
.hc-input--sm {
    padding: var(--hc-space-1) var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
}

.hc-input:focus {
    border-color: var(--hc-accent);
    outline: 2px solid var(--hc-accent-soft);
    outline-offset: 0;
}

/* --- Selects --------------------------------------------------------
   Closed control: our own chevron, inset from the right edge by the same
   space the text has on the left (no browser-default arrow jammed in the
   corner). Works in every browser. */
select.hc-input,
.hc-context-switch select {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%238A94A6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--hc-space-3) center;
    background-size: 12px 8px;
    padding-right: calc(var(--hc-space-3) * 2 + 12px);
    cursor: pointer;
    /* Keep a long value on one line. Blink forces overflow:visible on a select and
       ignores these two, but it clips the value at the content box anyway, and the
       padding-right above keeps that cut clear of the chevron. Engines that do
       honour them get an ellipsis instead of a hard cut. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Open dropdown: styled to match the app instead of the browser default.
   Progressive enhancement, browsers without customizable selects keep the
   native picker.

   Gated on ::selectedcontent as well as base-select, and that second condition
   is load-bearing rather than belt-and-braces. base-select turns the closed
   control into a flex box whose value is free to spill past the border, and
   because a select ignores author overflow, ::selectedcontent is the only hook
   that can trim it. A browser with base-select but no ::selectedcontent would
   render an untrimmable overflowing value, so it is better off on the plain
   chevron path above. */
@supports (appearance: base-select) and (selector(select::selectedcontent)) {
    select.hc-input,
    .hc-context-switch select {
        appearance: base-select;
        background-image: none;
        padding-right: var(--hc-space-3);
    }

    /* The value, as drawn inside the closed control. It is a flex item, so it
       needs min-width:0 before it will shrink below its own text width; without
       that it pushes the chevron out and runs past the border. */
    select.hc-input::selectedcontent,
    .hc-context-switch select::selectedcontent {
        display: block;
        min-width: 0;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }

    select.hc-input::picker-icon,
    .hc-context-switch select::picker-icon {
        color: var(--hc-text-muted);
        /* pin to the right edge; the select's right padding gives it the same
           breathing room the text has on the left */
        margin-left: auto;
        padding-left: var(--hc-space-2);
        /* the value yields before the chevron does */
        flex: none;
    }

    select.hc-input::picker(select),
    .hc-context-switch select::picker(select) {
        appearance: base-select;
        border: 1px solid var(--hc-border-subtle);
        border-radius: var(--hc-radius-sm);
        background-color: var(--hc-surface);
        box-shadow: var(--hc-shadow-pop);
        padding: var(--hc-space-1);
        margin-top: 4px;
        max-width: min(360px, calc(100vw - 24px));
    }

    select.hc-input option,
    .hc-context-switch select option {
        display: flex;
        align-items: center;
        gap: var(--hc-space-2);
        padding: var(--hc-space-2) var(--hc-space-3);
        border-radius: calc(var(--hc-radius-sm) - 4px);
        font-size: var(--hc-font-size-base);
        color: var(--hc-text);
        cursor: pointer;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    select.hc-input option:hover,
    select.hc-input option:focus,
    .hc-context-switch select option:hover,
    .hc-context-switch select option:focus {
        background-color: var(--hc-accent-soft);
    }

    select.hc-input option:checked,
    .hc-context-switch select option:checked {
        font-weight: 650;
    }

    select.hc-input option::checkmark,
    .hc-context-switch select option::checkmark {
        color: var(--hc-accent);
    }
}

.hc-validation-summary {
    color: var(--hc-danger);
    font-size: var(--hc-font-size-sm);
    margin: 0 0 var(--hc-space-3);
    padding-left: var(--hc-space-4);
}

.hc-validation-summary:empty {
    display: none;
}

.hc-validation-message {
    color: var(--hc-danger);
    font-size: var(--hc-font-size-sm);
}

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

.hc-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    column-gap: var(--hc-space-4);
}

.hc-form-grid .hc-form-field--full {
    grid-column: 1 / -1;
}

/* A long field beside a short one, for pairs like "Appliance" next to
   "Replacement value", where even columns starve the name and leave the number
   swimming. Explicit tracks rather than a span on the field, because the grid
   above is auto-fill: a field spanning 2 would invent an implicit column at
   narrow widths and push the form sideways.

   minmax(0, Nfr) rather than plain Nfr is what actually lets the select shrink,
   since a track floors at min-content by default and a long appliance name would
   otherwise widen the column instead of trimming. */
.hc-form-grid--lead {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
}

@media (max-width: 640px) {
    .hc-form-grid--lead {
        grid-template-columns: minmax(0, 1fr);
    }
}

.hc-form-section-title {
    grid-column: 1 / -1;
    font-size: var(--hc-font-size-sm);
    font-weight: 650;
    color: var(--hc-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: var(--hc-space-3) 0 var(--hc-space-3);
    padding-bottom: var(--hc-space-1);
    border-bottom: 1px solid var(--hc-border-subtle);
}

.hc-form-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-3);
    margin-top: var(--hc-space-4);
}

/* --- Alerts / status ---------------------------------------------- */

.hc-alert {
    padding: var(--hc-space-3) var(--hc-space-4);
    border-radius: var(--hc-radius-sm);
    font-size: var(--hc-font-size-sm);
    margin-bottom: var(--hc-space-4);
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
}

.hc-alert--success {
    background-color: var(--hc-success-soft);
    color: var(--hc-success);
}

.hc-alert--error {
    background-color: var(--hc-danger-soft);
    color: var(--hc-danger);
}

.hc-alert--warning {
    background-color: var(--hc-warning-soft);
    color: var(--hc-text);
}

.hc-alert--warning a {
    font-weight: 600;
}

/* --- Search box ------------------------------------------------------- */

.hc-search {
    position: relative;
    flex: 1;
    width: 100%;
    margin-bottom: var(--hc-space-4);
}

.hc-search > i {
    position: absolute;
    left: var(--hc-space-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--hc-text-muted);
    font-size: var(--hc-font-size-sm);
    pointer-events: none;
}

.hc-search input {
    width: 100%;
    padding-left: calc(var(--hc-space-3) * 2 + 1em);
    padding-right: calc(var(--hc-space-3) * 2 + 1em);
    border-radius: var(--hc-radius-full);
}

.hc-search input::-webkit-search-cancel-button {
    display: none;
}

.hc-search-clear {
    position: absolute;
    right: var(--hc-space-3);
    top: 50%;
    transform: translateY(-50%);
    border: none;
    background: none;
    color: var(--hc-text-muted);
    cursor: pointer;
    padding: var(--hc-space-1);
}

.hc-search-clear:hover {
    color: var(--hc-text);
}

/* --- Toasts (top-right) --------------------------------------------- */

.hc-toast-host {
    position: fixed;
    top: calc(58px + var(--hc-space-3));
    right: var(--hc-space-4);
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    max-width: min(360px, calc(100vw - 2 * var(--hc-space-4)));
}

.hc-toast {
    display: flex;
    align-items: flex-start;
    gap: var(--hc-space-3);
    padding: var(--hc-space-3) var(--hc-space-4);
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius);
    box-shadow: var(--hc-shadow-pop);
    font-size: var(--hc-font-size-sm);
    animation: hc-toast-in 0.2s ease-out;
}

.hc-toast i {
    margin-top: 2px;
}

.hc-toast--success i {
    color: var(--hc-success);
}

.hc-toast--error i {
    color: var(--hc-danger);
}

.hc-toast-close {
    margin-left: auto;
    border: none;
    background: none;
    color: var(--hc-text-muted);
    cursor: pointer;
    padding: 0 0 0 var(--hc-space-2);
}

@keyframes hc-toast-in {
    from {
        opacity: 0;
        transform: translateY(-6px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* --- Dropzone (Dropbox-style) ---------------------------------------- */

.hc-dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--hc-space-2);
    padding: var(--hc-space-6) var(--hc-space-4);
    border: 2px dashed var(--hc-border);
    border-radius: var(--hc-radius);
    background-color: var(--hc-surface-sunken);
    text-align: center;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.hc-dropzone i {
    font-size: 1.75rem;
    color: var(--hc-accent);
}

.hc-dropzone-title {
    font-weight: 650;
}

.hc-dropzone-hint {
    font-size: var(--hc-font-size-xs);
    color: var(--hc-text-muted);
}

.hc-dropzone input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

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

/* Archived rows fade back but stay legible. */
.hc-row-archived {
    opacity: 0.55;
}

/* --- Modal dialog (delete-or-archive choices) ------------------------ */

.hc-modal-backdrop {
    position: fixed;
    inset: 0;
    background-color: rgba(22, 35, 58, 0.45);
    z-index: 300;
}

.hc-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(460px, calc(100vw - 2 * var(--hc-space-4)));
    background-color: var(--hc-surface);
    border-radius: var(--hc-radius);
    box-shadow: var(--hc-shadow-pop);
    padding: var(--hc-space-5);
    z-index: 301;
}

/* Wider modal for embedded content (photos & receipts). */
.hc-modal--wide {
    width: min(680px, calc(100vw - 2 * var(--hc-space-4)));
    max-height: min(85vh, 720px);
    overflow-y: auto;
}

.hc-modal-close {
    position: absolute;
    top: var(--hc-space-3);
    right: var(--hc-space-3);
}

/* A section embedded in a modal drops its outer card chrome. */
.hc-modal .hc-section {
    margin-top: 0;
}

.hc-modal .hc-section .hc-card {
    border: none;
    box-shadow: none;
    padding: 0;
}

/* Small image preview beside the file name in linked-document tables. */
.hc-doc-thumb-link {
    display: inline-flex;
    align-items: center;
    gap: var(--hc-space-2);
}

.hc-doc-thumb {
    width: 44px;
    height: 44px;
    object-fit: cover;
    border-radius: calc(var(--hc-radius-sm) - 4px);
    border: 1px solid var(--hc-border-subtle);
}

/* --- Upload tray (bottom-right progress popups) ----------------------- */

.hc-upload-tray {
    position: fixed;
    right: var(--hc-space-4);
    bottom: var(--hc-space-4);
    z-index: 190;
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    width: min(340px, calc(100vw - 2 * var(--hc-space-4)));
}

@media (max-width: 960px) {
    .hc-upload-tray {
        bottom: calc(92px + env(safe-area-inset-bottom));
    }
}

.hc-upload-item {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    padding: var(--hc-space-3) var(--hc-space-4);
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius);
    box-shadow: var(--hc-shadow-pop);
    font-size: var(--hc-font-size-sm);
    animation: hc-toast-in 0.2s ease-out;
}

.hc-upload-item-header {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
}

.hc-upload-item-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}

.hc-progress {
    height: 6px;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-border-subtle);
    overflow: hidden;
}

.hc-progress-bar {
    height: 100%;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-accent);
    transition: width 0.15s ease;
}

/* --- File input (fallback) ------------------------------------------- */

.hc-file-input {
    font-size: var(--hc-font-size-sm);
}

.hc-file-input::file-selector-button {
    margin-right: var(--hc-space-3);
    padding: var(--hc-space-2) var(--hc-space-4);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    cursor: pointer;
}

/* --- Table -------------------------------------------------------- */

.hc-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--hc-font-size-sm);
}

.hc-table th {
    text-align: left;
    padding: var(--hc-space-2) var(--hc-space-3);
    color: var(--hc-text-muted);
    font-weight: 650;
    border-bottom: 1px solid var(--hc-border-subtle);
}

.hc-table td {
    padding: var(--hc-space-3);
    border-bottom: 1px solid var(--hc-border-subtle);
}

.hc-table .hc-table-actions {
    text-align: right;
    white-space: nowrap;
}

/* Mobile: each row becomes a stacked label/value block (the standard
   responsive-table pattern) — nothing ever overflows the card. */
@media (max-width: 640px) {
    .hc-table thead {
        display: none;
    }

    .hc-table tr {
        display: block;
        padding: var(--hc-space-3) 0;
        border-bottom: 1px solid var(--hc-border-subtle);
    }

    .hc-table tr:last-child {
        border-bottom: none;
    }

    .hc-table td {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        align-items: baseline;
        gap: var(--hc-space-1) var(--hc-space-4);
        padding: 3px 0;
        border-bottom: none;
        text-align: right;
    }

    /* Sub-lines inside a cell (serial numbers, notes, descriptions) take
       their own full line instead of squeezing beside the value. */
    .hc-table td > div {
        flex-basis: 100%;
    }

    .hc-table td::before {
        content: attr(data-label);
        flex-shrink: 0;
        font-size: var(--hc-font-size-xs);
        font-weight: 650;
        color: var(--hc-text-muted);
        text-transform: uppercase;
        letter-spacing: 0.04em;
        text-align: left;
    }

    .hc-table td:not([data-label]) {
        justify-content: flex-end;
    }

    .hc-table .hc-table-actions {
        padding-top: var(--hc-space-2);
    }
}

/* --- Key fact photos -------------------------------------------------- */

.hc-keyfact-photo {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: var(--hc-radius-sm);
    border: 1px solid var(--hc-border-subtle);
    display: block;
}

.hc-keyfact-photo-row {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
}

/* --- Pager (long lists page at ten) ---------------------------------- */

.hc-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--hc-space-3);
    margin-top: var(--hc-space-3);
}

.hc-pager-controls {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
}

.hc-pager-page {
    color: var(--hc-text-muted);
    white-space: nowrap;
}

/* --- Home dashboard (tip + widgets) ----------------------------------- */

/* Sunshine yellow, the visual language of "handy hint". */
.hc-home-tip {
    display: flex;
    align-items: flex-start;
    gap: var(--hc-space-3);
    padding: var(--hc-space-4);
    margin-bottom: var(--hc-space-4);
    background-color: var(--hc-warning-soft);
    border-radius: var(--hc-radius-lg);
}

.hc-home-tip img {
    width: 24px;
    height: 24px;
    margin-top: 2px;
    flex-shrink: 0;
}

.hc-home-tip-label {
    font-size: var(--hc-font-size-xs);
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--hc-warning);
}

.hc-home-tip p {
    margin: var(--hc-space-1) 0 0;
}

.hc-widget-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--hc-space-4);
    align-items: start;
}

/* Every widget is the same height, iPhone-style; growing a widget makes it
   wider and its content richer, never taller. */
.hc-widget {
    grid-column: span 1;
    height: 240px;
    display: flex;
    flex-direction: column;
    /* Anchors the pointer-shine overlay (::after, in the glow-up section). */
    position: relative;
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-lg);
    box-shadow: var(--hc-shadow-sm);
    padding: var(--hc-space-4);
    overflow: hidden;
    /* transform is in the list so the pointer tilt settles back smoothly when
       its class is removed, rather than snapping upright. */
    transition: opacity 0.15s ease, box-shadow 0.2s ease,
        border-color 0.2s ease, transform 0.18s ease;
}

.hc-widget-body {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.hc-widget-body .hc-widget-more {
    margin-top: auto;
    padding-top: var(--hc-space-2);
}

/* Charts inside widgets fit the fixed height rather than scaling with width. */
.hc-widget-chart {
    flex: 1;
    min-height: 0;
}

.hc-widget-chart svg {
    height: 100% !important;
    width: 100% !important;
}

.hc-widget--m {
    grid-column: span 2;
}

.hc-widget--l {
    grid-column: 1 / -1;
}

@media (max-width: 960px) {
    .hc-widget-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 640px) {
    .hc-widget-grid {
        grid-template-columns: 1fr;
    }

    .hc-widget,
    .hc-widget--m {
        grid-column: span 1;
    }
}

.hc-widget-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-3);
}

.hc-widget-title {
    font-size: var(--hc-font-size-xs);
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--hc-text-muted);
}

.hc-widget-title i {
    color: var(--hc-accent);
    margin-right: var(--hc-space-1);
}

.hc-widget-controls {
    display: inline-flex;
    gap: var(--hc-space-1);
}

/* iPhone-style wobble says "you're editing"; drags feel natural from it. */
.hc-widget--edit {
    cursor: grab;
    animation: hc-widget-wobble 0.35s ease-in-out infinite alternate;
}

/* While a drag is live: freeze the wobble (a moving transform makes drop
   targets jitter) and let only whole widgets receive drag events, so
   dragenter doesn't storm from every child element. */
.hc-widget-grid--dragging .hc-widget {
    animation: none;
}

.hc-widget-grid--dragging .hc-widget > * {
    pointer-events: none;
}

.hc-widget--dragging {
    opacity: 0.4;
    border-style: dashed;
    box-shadow: none;
}

@keyframes hc-widget-wobble {
    from { transform: rotate(-0.3deg); }
    to { transform: rotate(0.3deg); }
}

@media (prefers-reduced-motion: reduce) {
    .hc-widget--edit {
        animation: none;
    }
}

.hc-widget-hero {
    font-size: 28px;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.hc-widget-stats {
    display: flex;
    gap: var(--hc-space-5);
    margin-bottom: var(--hc-space-2);
}

.hc-widget-bad {
    color: var(--hc-danger);
}

.hc-widget-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-1);
}

.hc-widget-list a {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    padding: var(--hc-space-1) 0;
    color: var(--hc-text);
}

.hc-widget-list i {
    width: 18px;
    text-align: center;
    color: var(--hc-text-muted);
}

.hc-widget-list-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--hc-font-size-sm);
}

.hc-widget-more {
    display: inline-block;
    margin-top: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
}

.hc-widget-add-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
}

.hc-widget-search {
    flex-shrink: 0;
}

/* --- Home glow-up (entrance, 3D presence, greeting) --------------------
   All motion here is opacity/transform only, so it stays on the compositor
   and never moves a click target. Everything switches off together under
   prefers-reduced-motion at the end of the section. */

/* Entrance choreography: the greeting rises first, the widgets follow with a
   small stagger. The per-widget delay rides in --hc-enter-delay, set inline
   from the loop index in Home.razor; "backwards" keeps a delayed widget
   invisible until its turn. Home.razor stops emitting these classes the
   moment customise mode starts, so edit-time class churn can't replay the
   entrance (a changed animation-name restarts a CSS animation). */
.hc-home-hero-in {
    animation: hc-rise-in 420ms cubic-bezier(0.32, 0.72, 0, 1) backwards;
}

.hc-widget-in {
    animation: hc-rise-in 380ms cubic-bezier(0.32, 0.72, 0, 1) backwards;
    animation-delay: var(--hc-enter-delay, 0ms);
}

@keyframes hc-rise-in {
    from {
        opacity: 0;
        transform: translate3d(0, 10px, 0);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* 3D presence: one shared vanishing point for the whole grid, so neighbouring
   cards tilt as if lit and viewed from the same place. perspective adds no
   layout, so the drag/customise grid maths is untouched. */
.hc-widget-grid {
    perspective: 1100px;
}

/* The pointer tilt. homeFx.js sets the custom properties and this class from
   pointer position; CSS owns what they mean. The base .hc-widget transition
   carries the card back upright when the class goes. */
.hc-widget--tilt {
    transform: rotateX(var(--hc-tilt-rx, 0deg)) rotateY(var(--hc-tilt-ry, 0deg));
    will-change: transform;
}

/* The moving shine: a soft accent-tinted glare that follows the pointer.
   --hc-cloud is the palette's near-white in both themes, so the sheen reads
   as light (not a dark smudge) on dark surfaces too. pointer-events: none
   keeps every click target underneath it live. */
.hc-widget::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: var(--hc-shine-o, 0);
    transition: opacity 0.25s ease;
    background: radial-gradient(
        260px circle at var(--hc-shine-x, 50%) var(--hc-shine-y, 40%),
        color-mix(in srgb, color-mix(in srgb, var(--hc-accent) 22%, var(--hc-cloud)) 16%, transparent),
        transparent 65%);
}

/* Depth on hover: the layered shadow deepens and picks up a whisper of the
   accent, in the glow and on the border. Token-derived, so it follows the
   member's accent theme and both colour schemes. hover-gated so touch
   devices never wear a stuck hover state. */
@media (hover: hover) {
    .hc-widget:hover {
        box-shadow: var(--hc-shadow),
            0 8px 28px color-mix(in srgb, var(--hc-accent) 10%, transparent);
        border-color: color-mix(in srgb, var(--hc-accent) 22%, var(--hc-border-subtle));
    }
}

/* The greeting: a fixed accent sheen across the lettering (background-clip
   keeps the glyph shapes), and a one-time underline draw. The underline is
   absolutely positioned into the h1's existing bottom margin so the header
   layout does not move by a pixel. */
.hc-home-greeting {
    position: relative;
    background-image: linear-gradient(100deg,
        var(--hc-text) 55%, var(--hc-accent) 78%, var(--hc-text) 92%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hc-home-greeting::after {
    content: "";
    position: absolute;
    left: 2px;
    bottom: -5px;
    width: 64px;
    height: 3px;
    border-radius: var(--hc-radius-full);
    background: linear-gradient(90deg, var(--hc-accent), var(--hc-highlight));
    transform-origin: left;
    animation: hc-underline-draw 600ms 300ms cubic-bezier(0.32, 0.72, 0, 1) backwards;
}

@keyframes hc-underline-draw {
    from {
        transform: scaleX(0);
    }
}

/* Reduced motion: instant final states. The underline shows fully drawn, the
   figures and cards are simply there, the shine and tilt never engage
   (homeFx.js also refuses to drive them, this is the belt to its braces). */
@media (prefers-reduced-motion: reduce) {
    .hc-home-hero-in,
    .hc-widget-in,
    .hc-home-greeting::after {
        animation: none;
    }

    .hc-widget--tilt {
        transform: none;
    }

    .hc-widget::after {
        transition: none;
        opacity: 0;
    }
}

/* --- Document folders (Dropbox-style rows) --------------------------- */

/* The folder name cell is a button so the whole label opens the folder. */
.hc-folder-open {
    display: inline-flex;
    align-items: center;
    gap: var(--hc-space-2);
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    color: var(--hc-text);
    font: inherit;
    text-align: left;
}

.hc-folder-open i {
    color: var(--hc-accent);
    font-size: 18px;
}

.hc-folder-open:hover strong {
    color: var(--hc-accent);
}

/* Highlight while an OS file drag hovers the row (documentsPage.js). */
.hc-folder-row--drop > td {
    background-color: var(--hc-accent-soft);
}

/* Breadcrumb back into the folder list. */
.hc-breadcrumb {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-3);
    font-weight: 600;
}

.hc-breadcrumb button {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    color: var(--hc-accent);
    font: inherit;
}

.hc-breadcrumb button:hover {
    color: var(--hc-accent-hover);
}

.hc-breadcrumb .hc-breadcrumb-sep {
    color: var(--hc-text-muted);
}

/* --- Empty state --------------------------------------------------- */

.hc-empty-state {
    text-align: center;
    padding: var(--hc-space-7) var(--hc-space-5);
    color: var(--hc-text-muted);
}

.hc-empty-state h3 {
    color: var(--hc-text);
}

/* --- Auth pages ---------------------------------------------------- */

/* Full-viewport centring for every pre-sign-in screen. */
.hc-auth-viewport {
    min-height: 100dvh;
    display: grid;
    place-items: center;
    padding: var(--hc-space-4);
}

.hc-auth-card {
    max-width: 420px;
    width: 100%;
    margin: 0 auto;
}

/* Logo + product name at the top of the auth card. */
.hc-auth-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-4);
}

.hc-auth-brand img {
    width: 52px;
    height: 52px;
}

.hc-auth-brand span {
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--hc-text);
    letter-spacing: -0.01em;
}

.hc-auth-links {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    margin-top: var(--hc-space-4);
    font-size: var(--hc-font-size-sm);
}

/* Card footer: divider then a centred row of quiet links, the shape most
   sign-in screens settle on. */
.hc-auth-footer {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--hc-space-3);
    margin-top: var(--hc-space-5);
    padding-top: var(--hc-space-4);
    border-top: 1px solid var(--hc-border-subtle);
    font-size: var(--hc-font-size-sm);
}

.hc-auth-footer-dot {
    color: var(--hc-text-muted);
}

/* --- Back link (Apple-style ‹ Parent) -------------------------------- */

.hc-back {
    display: inline-flex;
    align-items: center;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-3);
    color: var(--hc-accent);
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
}

.hc-back i {
    font-size: var(--hc-font-size-xs);
}

.hc-back:hover {
    color: var(--hc-accent-hover);
    text-decoration: none;
}

.hc-back--mobile {
    display: none;
}

@media (max-width: 960px) {
    .hc-back--mobile {
        display: inline-flex;
    }
}

/* --- Page header ---------------------------------------------------- */

.hc-page-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--hc-space-3);
    flex-wrap: wrap;
    margin-bottom: var(--hc-space-5);
}

.hc-page-header p {
    margin: 0;
}

/* --- Fact grid (label/value pairs) ---------------------------------- */

.hc-facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--hc-space-4);
}

/* Grid items refuse to shrink below their longest word by default, so an
   unbroken value (a file name, a reference number, a URL) would widen the
   whole page on a phone; let it break mid-word instead. */
.hc-facts > div {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* --- Inventory item link + detail panel ----------------------------- */

/* A name that goes somewhere: works as an <a> (appliance page) or a <button>
   (detail panel), styled identically so the row reads as one pattern. */
.hc-item-link {
    display: inline;
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    font-weight: inherit;
    color: var(--hc-accent);
    text-align: left;
    cursor: pointer;
}

.hc-item-link:hover {
    color: color-mix(in srgb, var(--hc-accent) 80%, var(--hc-text));
}

.hc-item-link-chevron {
    font-size: 0.7em;
    opacity: 0.55;
}

.hc-detail-receipt {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    margin: 0 0 var(--hc-space-3);
}

.hc-detail-warranties {
    margin: 0 0 var(--hc-space-3);
    padding-left: var(--hc-space-4);
}

.hc-detail-warranties li {
    margin-bottom: var(--hc-space-1);
}

.hc-fact-label {
    font-size: var(--hc-font-size-xs);
    font-weight: 650;
    color: var(--hc-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.hc-fact-value {
    font-size: var(--hc-font-size-base);
}

/* --- Detail sections ------------------------------------------------- */

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

.hc-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--hc-space-3);
    /* On a phone a long title plus a reference badge cannot share a line;
       wrapping drops the badge group neatly below the title instead of
       squeezing the title to a word a line and pushing the badge off screen. */
    flex-wrap: wrap;
    margin-bottom: var(--hc-space-3);
}

.hc-section-header h2 {
    margin: 0;
}

/* Grouped actions on the right of a section header keep their spacing when
   they wrap onto separate lines on mobile. */
.hc-section-header > div {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--hc-space-2);
}

.hc-inline-form {
    background-color: var(--hc-surface-sunken);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-sm);
    padding: var(--hc-space-4);
    margin-top: var(--hc-space-3);
}

/* Add/edit forms open at the TOP of their card: the user sees the form
   immediately instead of having to know to scroll past existing records.
   DOM order stays as-is, only the visual order changes. */
.hc-card:has(> .hc-inline-form) {
    display: flex;
    flex-direction: column;
}

.hc-card > .hc-inline-form {
    order: -1;
    margin-top: 0;
    margin-bottom: var(--hc-space-3);
}

/* Same rule for add forms that aren't styled as inline forms (inventory). */
.hc-card:has(> .hc-card-form) {
    display: flex;
    flex-direction: column;
}

.hc-card > .hc-card-form {
    order: -1;
    margin-top: 0;
    margin-bottom: var(--hc-space-3);
}

/* --- Photo grid ------------------------------------------------------- */

.hc-photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--hc-space-3);
}

.hc-photo {
    position: relative;
    aspect-ratio: 4 / 3;
    border-radius: var(--hc-radius-sm);
    overflow: hidden;
    border: 1px solid var(--hc-border-subtle);
}

.hc-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.hc-photo-remove {
    position: absolute;
    top: var(--hc-space-2);
    right: var(--hc-space-2);
    padding: var(--hc-space-1) var(--hc-space-2);
    border: none;
    border-radius: var(--hc-radius-sm);
    background-color: color-mix(in srgb, var(--hc-ink) 70%, transparent);
    color: #ffffff;
    font-size: var(--hc-font-size-xs);
    cursor: pointer;
}

/* --- Blazor framework UI ------------------------------------------- */

/* The unhandled-error banner (blazor.web.js flips it to display:block).
   A floating card rather than the template's full-width strip, so it
   reads as ours: surface, radius and shadow from the tokens, the
   reload action in the accent. */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: var(--hc-space-5);
    left: 50%;
    transform: translateX(-50%);
    z-index: 1000;
    max-width: min(440px, calc(100vw - 2 * var(--hc-space-4)));
    padding: var(--hc-space-3) var(--hc-space-6) var(--hc-space-3) var(--hc-space-4);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-size: var(--hc-font-size-sm);
    box-shadow: var(--hc-shadow-pop);
}

#blazor-error-ui .reload {
    color: var(--hc-accent);
    font-weight: 600;
}

#blazor-error-ui .dismiss {
    position: absolute;
    right: var(--hc-space-3);
    top: var(--hc-space-2);
    cursor: pointer;
    color: var(--hc-text-muted);
}

/* --- Error & not-found pages ---------------------------------------
   Shared by /Error (the exception handler page) and /not-found. The
   pig is the fun; the words stay warm and brief. */
.hc-error-page {
    max-width: 480px;
    margin: 0 auto;
    padding: var(--hc-space-7) var(--hc-space-4);
    text-align: center;
}

.hc-error-page .hc-pig--full {
    width: 160px;
    height: 160px;
    margin-bottom: var(--hc-space-4);
}

.hc-error-page h1 {
    font-size: var(--hc-font-size-2xl);
    margin: 0 0 var(--hc-space-2);
}

.hc-error-page p {
    color: var(--hc-text-muted);
    margin: 0 0 var(--hc-space-5);
}

.hc-error-requestid {
    margin-top: var(--hc-space-6);
    font-size: var(--hc-font-size-xs);
    color: var(--hc-text-muted);
}

.hc-error-requestid code {
    font-size: inherit;
}

.blazor-error-boundary {
    padding: var(--hc-space-4);
    border-radius: var(--hc-radius-sm);
    background-color: var(--hc-danger-soft);
    color: var(--hc-danger);
}

.validation-errors {
    color: var(--hc-danger);
    font-size: var(--hc-font-size-sm);
}

/* --- Renewal radar ------------------------------------------------- */

.hc-radar-card {
    padding: var(--hc-space-2);
}

.hc-radar-row {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    padding: var(--hc-space-3);
    border-radius: var(--hc-radius-sm);
    color: inherit;
    text-decoration: none;
    transition: background-color 0.15s ease;
}

.hc-radar-row:hover {
    background-color: var(--hc-surface-sunken);
}

.hc-radar-icon {
    flex: none;
    width: 38px;
    height: 38px;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
    font-size: 15px;
}

.hc-radar-body {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.hc-radar-title {
    font-weight: 600;
}

.hc-radar-when {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    flex: none;
}

.hc-radar-date {
    font-size: var(--hc-font-size-sm);
    color: var(--hc-text-muted);
}

/* --- Notification bell ---------------------------------------------- */

.hc-bell-wrap {
    position: relative;
}

.hc-bell {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: none;
    border-radius: var(--hc-radius-full);
    background: none;
    color: var(--hc-text-muted);
    font-size: 17px;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.hc-bell:hover {
    background-color: var(--hc-accent-soft);
    color: var(--hc-text);
}

.hc-bell-badge {
    position: absolute;
    top: 1px;
    right: 0;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-danger);
    color: #ffffff;
    font-size: 11px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--hc-surface);
}

.hc-bell-backdrop {
    position: fixed;
    inset: 0;
    z-index: 90;
}

.hc-bell-panel {
    /* Fixed, not absolute: the panel now renders outside the topbar (whose
       backdrop-filter traps fixed descendants), pinned under the bell's
       corner. 58px topbar plus a whisker of air. */
    position: fixed;
    top: 66px;
    right: 16px;
    z-index: 301;
    width: 340px;
    max-width: calc(100vw - 24px);
    max-height: 70vh;
    overflow-y: auto;
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius);
    box-shadow: var(--hc-shadow-pop);
    padding: var(--hc-space-2);
}

.hc-bell-panel-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--hc-space-3);
    padding: var(--hc-space-2) var(--hc-space-3);
    border-bottom: 1px solid var(--hc-border-subtle);
    margin-bottom: var(--hc-space-2);
}

.hc-bell-empty {
    padding: var(--hc-space-3);
    margin: 0;
}

.hc-bell-row {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    padding: var(--hc-space-2) var(--hc-space-3);
    border-radius: var(--hc-radius-sm);
    color: inherit;
    text-decoration: none;
}

.hc-bell-row:hover {
    background-color: var(--hc-surface-sunken);
    text-decoration: none;
}

.hc-bell-row-icon {
    width: 32px;
    height: 32px;
    border-radius: 10px;
    font-size: 13px;
}

.hc-bell-row-body {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.hc-bell-row-title {
    font-weight: 600;
    font-size: var(--hc-font-size-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hc-bell-view-all {
    display: block;
    text-align: center;
    padding: var(--hc-space-3);
    margin-top: var(--hc-space-1);
    border-top: 1px solid var(--hc-border-subtle);
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
}

/* --- Property valuation --------------------------------------------- */

.hc-valuation-hero {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--hc-space-4);
    flex-wrap: wrap;
}

.hc-valuation-figure {
    font-size: 2.2rem;
    font-weight: 700;
    margin: 0;
    line-height: 1.1;
}

.hc-valuation-deltas {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--hc-space-2);
}

/* Card on /properties: main area links to the property, the strip below
   links to its valuation on /costs. */
.hc-property-card {
    padding: 0;
    display: flex;
    flex-direction: column;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.hc-property-card:hover {
    box-shadow: var(--hc-shadow);
    transform: translateY(-2px);
}

.hc-property-card-main {
    display: block;
    padding: var(--hc-space-5);
    color: inherit;
    flex: 1;
}

.hc-property-card-main:hover {
    color: inherit;
    text-decoration: none;
}

.hc-valuation-strip {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--hc-space-3);
    padding: var(--hc-space-3) var(--hc-space-5);
    border-top: 1px solid var(--hc-border-subtle);
    background-color: var(--hc-surface-sunken);
    border-radius: 0 0 var(--hc-radius-lg) var(--hc-radius-lg);
    color: inherit;
}

.hc-valuation-strip:hover {
    text-decoration: none;
    color: inherit;
    background-color: var(--hc-accent-soft);
}

.hc-valuation-strip-body {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.hc-valuation-strip-value {
    font-weight: 650;
    font-size: var(--hc-font-size-sm);
}

/* --- Address finder (property setup) ------------------------------- */

.hc-address-finder {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
}

/* min-width: 0 beats the input's intrinsic minimum, which otherwise pushes
   the sibling button off a phone screen (seen on the inventory add-room row). */
.hc-address-finder .hc-input {
    flex: 1 1 160px;
    min-width: 0;
}

/* --- Moving on (archive + handover) --------------------------------- */

.hc-moving-on {
    margin-top: var(--hc-space-5);
}

.hc-moving-on-section {
    max-width: 560px;
}

.hc-moving-on-section + .hc-moving-on-section {
    margin-top: var(--hc-space-5);
    padding-top: var(--hc-space-5);
    border-top: 1px solid var(--hc-border-subtle);
}

.hc-transfer-appliances {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    margin: var(--hc-space-3) 0 var(--hc-space-4);
}

/* Rows whose labels run to two lines (title + muted description), so
   the box aligns with the first line rather than floating mid-block.
   The 1px nudge centres the 20px box against the 21px first line. */
.hc-check-row {
    display: flex;
    align-items: flex-start;
    gap: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    cursor: pointer;
}

/* The label itself is 550 by house rule; the sentence of explanation under
   it is prose, and prose is not a label. */
.hc-check-row .hc-text-muted {
    font-weight: 400;
}

.hc-check-row input[type="checkbox"] {
    margin-top: 1px;
}

.hc-transfer-form {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
    align-items: flex-start;
}

.hc-transfer-form .hc-form-field {
    width: 100%;
    max-width: 320px;
}

/* --- XP ring (header) + level-up ------------------------------------ */

.hc-xp {
    display: inline-flex;
    align-items: center;
}

.hc-xp-ring {
    width: 34px;
    height: 34px;
    display: block;
}

.hc-xp-track {
    fill: none;
    stroke: var(--hc-border-subtle);
    stroke-width: 3;
}

.hc-xp-progress {
    fill: none;
    stroke: var(--hc-accent);
    stroke-width: 3;
    stroke-linecap: round;
    transition: stroke-dashoffset 0.6s ease;
}

.hc-xp-level {
    fill: var(--hc-text);
    font-size: 14px;
    font-weight: 700;
    text-anchor: middle;
    dominant-baseline: middle;
}

.hc-levelup {
    text-align: center;
}

.hc-levelup-badge svg {
    width: 72px;
    height: 72px;
    margin: 0 auto var(--hc-space-3);
    display: block;
}

.hc-levelup-badge .hc-xp-level {
    font-size: 15px;
}

.hc-levelup-full {
    stroke: var(--hc-accent);
}

.hc-levelup-actions {
    justify-content: center;
    flex-wrap: wrap;
}

/* --- Email-in address (Settings) ------------------------------------- */

.hc-inbox-address {
    padding: var(--hc-space-2) var(--hc-space-3);
    background-color: var(--hc-surface-sunken);
    border-radius: var(--hc-radius-sm);
    font-size: var(--hc-font-size-sm);
    word-break: break-all;
}

/* --- Assistant chat --------------------------------------------------- */

.hc-chat-fab {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 95;
    width: 56px;
    height: 56px;
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    color: var(--hc-accent);
    font-size: 22px;
    cursor: pointer;
    box-shadow: var(--hc-shadow-pop);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.15s ease, background-color 0.15s ease;
}

.hc-chat-fab:hover {
    transform: scale(1.06);
}

/* The homehog is the chat button: it sits in the bubble and idles away. It
   ages like it does everywhere else, and the head grows by ~87% from level 1
   to 30, so the box is sized to keep a baby readable and an old hog inside the
   56px bubble. pointer-events off so every click lands on the button. */
.hc-chat-fab .hc-pig {
    width: 46px;
    height: 46px;
    margin: 0 auto;
    pointer-events: none;
}

.hc-chat-title {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
}

.hc-chat-avatar {
    width: 34px;
    height: 34px;
}

/* Pops back in when the chat closes. */
.hc-chat-fab {
    animation: hc-chat-fab-in 0.18s ease-out;
}

@keyframes hc-chat-fab-in {
    from { transform: scale(0.4); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}

/* The panel takes the bubble's corner and grows out of it: it starts as a
   bubble-sized circle at the exact FAB position and morphs into the chat. */
.hc-chat-panel {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 96;
    width: 390px;
    max-width: calc(100vw - 40px);
    height: 600px;
    max-height: calc(100vh - 110px);
    display: flex;
    flex-direction: column;
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-lg);
    box-shadow: var(--hc-shadow-pop);
    overflow: hidden;
    transform-origin: calc(100% - 28px) calc(100% - 28px);
    animation: hc-chat-morph 0.28s cubic-bezier(0.2, 0.8, 0.3, 1);
}

@keyframes hc-chat-morph {
    0% { transform: scale(0.14); border-radius: 50%; opacity: 0.4; }
    55% { border-radius: 28px; }
    100% { transform: scale(1); border-radius: var(--hc-radius-lg); opacity: 1; }
}

.hc-chat-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--hc-space-3);
    padding: var(--hc-space-3) var(--hc-space-4);
    border-bottom: 1px solid var(--hc-border-subtle);
}

.hc-chat-messages {
    flex: 1;
    min-height: 0; /* a flex child won't scroll without this, it just grows */
    overflow-y: auto;
    /* The conversation is the only thing that scrolls: reaching either end
       must not start dragging the page behind it. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: var(--hc-space-4);
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
}

.hc-chat-msg--user {
    align-self: flex-end;
    text-align: right;
    max-width: 85%;
}

.hc-chat-msg--assistant {
    align-self: flex-start;
    max-width: 90%;
}

.hc-chat-msg-author {
    font-size: var(--hc-font-size-xs);
    font-weight: 650;
    color: var(--hc-text-muted);
    margin-bottom: 2px;
}

.hc-chat-bubble {
    display: inline-block;
    text-align: left;
    padding: var(--hc-space-2) var(--hc-space-3);
    border-radius: var(--hc-radius);
    background-color: var(--hc-surface-sunken);
    font-size: var(--hc-font-size-sm);
    line-height: 1.5;
}

.hc-chat-msg--user .hc-chat-bubble {
    background-color: var(--hc-accent-soft);
}

.hc-chat-bullet {
    padding-left: var(--hc-space-4);
    position: relative;
}

.hc-chat-bullet::before {
    content: "\2022";
    position: absolute;
    left: var(--hc-space-2);
}

.hc-chat-gap {
    height: var(--hc-space-2);
}

.hc-chat-suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    padding: 0 var(--hc-space-4) var(--hc-space-3);
}

.hc-chat-chip {
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-size: var(--hc-font-size-xs);
    font-weight: 550;
    padding: 6px 12px;
    cursor: pointer;
}

.hc-chat-chip:hover {
    background-color: var(--hc-accent-soft);
    border-color: var(--hc-accent);
}

.hc-chat-input-row {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    padding: var(--hc-space-3) var(--hc-space-4);
    border-top: 1px solid var(--hc-border-subtle);
}

.hc-chat-input-row .hc-input {
    flex: 1;
}

.hc-chat-send {
    color: var(--hc-accent);
    font-size: 17px;
}

/* Hover inverts it rather than washing it grey like a plain icon button:
   the pink moves from the plane to the pad behind it. */
.hc-chat-send:hover:not(:disabled) {
    background-color: var(--hc-accent);
    color: var(--hc-on-accent);
}

.hc-chat-send:disabled {
    opacity: 0.4;
    cursor: default;
}

/* Typing indicator: three pulsing dots. */
.hc-chat-thinking {
    display: inline-flex;
    gap: 5px;
    align-items: center;
}

.hc-chat-thinking span {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: var(--hc-text-muted);
    animation: hc-chat-dot 1.2s ease-in-out infinite;
}

.hc-chat-thinking span:nth-child(2) { animation-delay: 0.15s; }
.hc-chat-thinking span:nth-child(3) { animation-delay: 0.3s; }

@keyframes hc-chat-dot {
    0%, 100% { opacity: 0.35; transform: translateY(0); }
    50% { opacity: 1; transform: translateY(-3px); }
}

/* Whenever the bottom tab bar is showing, the bubble floats clearly above
   it: bar top sits around 64px, so 96px leaves a proper gap rather than the
   pig grazing the glass. */
@media (max-width: 960px) {
    .hc-chat-fab {
        bottom: calc(96px + env(safe-area-inset-bottom));
    }
}

/* Mobile: the chat takes the whole screen, standard for support widgets.
   Sized to the device rather than the layout viewport: dvh tracks the browser
   chrome as it hides and shows, so the input row never ends up under it. */
@media (max-width: 640px) {
    .hc-chat-panel {
        inset: 0;
        width: 100vw;
        max-width: none;
        height: 100dvh;
        max-height: 100dvh;
        border-radius: 0;
        border: none;
        z-index: 120; /* above the tab bar */
        padding-bottom: env(safe-area-inset-bottom);
        animation: hc-chat-slide-up 0.25s ease-out; /* full screen slides up instead of morphing */
    }
}

@keyframes hc-chat-slide-up {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .hc-chat-thinking span {
        animation: none;
    }

    .hc-chat-fab,
    .hc-chat-panel {
        animation: none;
    }
}

/* --- AI photo analysis ----------------------------------------------- */

/* Shown while the vision model reads an uploaded photo. */
.hc-ai-banner {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    margin: var(--hc-space-3) 0;
    color: var(--hc-accent);
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
}

.hc-ai-banner i {
    animation: hc-ai-pulse 1.2s ease-in-out infinite;
}

@keyframes hc-ai-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.45; transform: scale(0.9); }
}

/* The inputs the AI is about to fill shimmer until the answer lands. */
.hc-ai-analyzing .hc-input {
    color: transparent;
    pointer-events: none;
    background: linear-gradient(90deg,
        var(--hc-surface-sunken) 25%,
        color-mix(in srgb, var(--hc-surface) 70%, var(--hc-surface-sunken)) 50%,
        var(--hc-surface-sunken) 75%);
    background-size: 200% 100%;
    animation: hc-ai-input-shimmer 1.4s ease-in-out infinite;
}

@keyframes hc-ai-input-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .hc-ai-banner i,
    .hc-ai-analyzing .hc-input {
        animation: none;
    }
}

/* --- Skeleton loading (shimmer) --------------------------------------- */

.hc-skeleton {
    position: relative;
    overflow: hidden;
    background-color: var(--hc-surface-sunken);
    border-radius: var(--hc-radius-sm);
}

.hc-skeleton--circle {
    border-radius: 50%;
}

.hc-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg,
        transparent,
        color-mix(in srgb, var(--hc-surface) 70%, transparent),
        transparent);
    animation: hc-shimmer 1.4s ease-in-out infinite;
}

@keyframes hc-shimmer {
    100% { transform: translateX(100%); }
}

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

/* The search box's placeholder carries the same bottom margin the real SearchBox
   does, so swapping one for the other doesn't shift the page. */
.hc-skeleton-search {
    margin-bottom: var(--hc-space-4);
}

/* An input is squarer than a text bar; matching its radius stops the placeholder
   reading as a paragraph where a box is about to appear. */
.hc-skeleton--input {
    border-radius: var(--hc-radius-sm);
}

.hc-skeleton-group {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
}

.hc-skeleton-header {
    margin-bottom: var(--hc-space-5);
}

.hc-skeleton-row {
    display: flex;
    gap: var(--hc-space-4);
    align-items: center;
}

.hc-skeleton-row--head {
    padding-bottom: var(--hc-space-2);
    border-bottom: 1px solid var(--hc-border-subtle);
}

.hc-skeleton-facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--hc-space-4);
}

/* --- Progress page + badges ------------------------------------------ */

.hc-progress-hero {
    display: flex;
    align-items: center;
    gap: var(--hc-space-5);
}

.hc-progress-hero h2,
.hc-progress-hero p {
    margin: 0 0 var(--hc-space-1);
}

/* The hero ring frames the pig instead of a number, so it's sized to hold one. */
.hc-progress-pigring {
    position: relative;
    display: grid;
    place-items: center;
    width: 168px;
    height: 168px;
    flex: none;
}

.hc-progress-ring {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Stroke 3 was drawn for a 96px ring; at 168px it reads as a hoop. */
.hc-progress-pigring .hc-xp-track,
.hc-progress-pigring .hc-xp-progress {
    stroke-width: 2;
}

.hc-progress-badges-title {
    margin-top: var(--hc-space-6);
}

.hc-badge-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: var(--hc-space-3);
}

.hc-badge-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--hc-space-2);
    padding: var(--hc-space-4) var(--hc-space-2);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-lg);
    background-color: var(--hc-surface);
    font-family: inherit;
    color: var(--hc-text);
    cursor: pointer;
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}

.hc-badge-tile:hover {
    box-shadow: var(--hc-shadow-sm);
    transform: translateY(-1px);
}

.hc-badge-tile--locked {
    opacity: 0.45;
    filter: grayscale(1);
}

.hc-badge-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
    font-size: 19px;
    flex: none;
}

.hc-badge-icon--big {
    width: 64px;
    height: 64px;
    font-size: 26px;
    margin: 0 auto var(--hc-space-3);
}

.hc-badge-name {
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    text-align: center;
}

.hc-badge-earned {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    text-align: left;
    padding: var(--hc-space-2) 0;
}

.hc-badge-earned p {
    margin: 0;
}

/* --- Print (lawyer pack and any report) ----------------------------- */

@media print {
    .hc-sidebar,
    .hc-topbar,
    .hc-tabbar,
    .hc-toast-host,
    .hc-no-print {
        display: none !important;
    }

    .hc-main {
        max-width: none;
        padding: 0;
    }

    .hc-card {
        box-shadow: none;
        border: 1px solid #ddd;
        break-inside: avoid;
    }
}

/* --- The homehog: idle pig avatar (see js/pig.js) --- */
.hc-pig {
    display: block;
    flex-shrink: 0;
}

.hc-pig svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.hc-pig--head {
    width: 40px;
    height: 40px;
}

.hc-pig--full {
    width: 200px;
    height: 200px;
    margin: 0 auto;
}

/* Ambient motion: always running, the pig is never completely still. */
@keyframes hc-pig-floatbob {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-2px); }
}

.hc-pig [data-p="float"] {
    animation: hc-pig-floatbob 3.6s ease-in-out infinite;
}

@keyframes hc-pig-breathe {
    0%, 100% { transform: scaleY(1) scaleX(1); }
    50% { transform: scaleY(1.025) scaleX(.995); }
}

.hc-pig [data-p="breathe"] {
    animation: hc-pig-breathe 3.4s ease-in-out infinite;
    transform-origin: 150px 210px;
    transform-box: view-box;
}

/* Transient actions, fired on random timers by pig.js. */
@keyframes hc-pig-blink {
    0%, 100% { transform: scaleY(1); }
    45%, 60% { transform: scaleY(.08); }
}

@keyframes hc-pig-nod {
    0%, 100% { transform: translateY(0); }
    30% { transform: translateY(4px); }
    58% { transform: translateY(-2px); }
    80% { transform: translateY(1px); }
}

@keyframes hc-pig-sway {
    0%, 100% { transform: rotate(0); }
    25% { transform: rotate(4deg); }
    75% { transform: rotate(-4deg); }
}

@keyframes hc-pig-hop {
    0%, 100% { transform: translateY(0); }
    30% { transform: translateY(-26px); }
    55% { transform: translateY(0); }
    70% { transform: translateY(-7px); }
    85% { transform: translateY(0); }
}

@keyframes hc-pig-wag {
    0%, 100% { transform: rotate(0); }
    50% { transform: rotate(-26deg); }
}

@keyframes hc-pig-eartw {
    0%, 100% { transform: rotate(0); }
    30% { transform: rotate(-13deg); }
    60% { transform: rotate(3deg); }
}

@keyframes hc-pig-wiggle {
    0%, 100% { transform: rotate(0); }
    25% { transform: rotate(3.5deg); }
    75% { transform: rotate(-3.5deg); }
}

@keyframes hc-pig-sniff {
    0%, 100% { transform: translateY(0) scale(1); }
    50% { transform: translateY(1.5px) scale(1.05); }
}

@keyframes hc-pig-yawn {
    0%, 100% { transform: scaleY(1); }
    40%, 60% { transform: scaleY(1.9) scaleX(1.1); }
}

.hc-pig .a-blink { animation: hc-pig-blink .34s ease-in-out; }
.hc-pig .a-nod { animation: hc-pig-nod .9s ease-in-out; }
.hc-pig .a-sway { animation: hc-pig-sway 1.1s ease-in-out; }
.hc-pig .a-hop { animation: hc-pig-hop .95s cubic-bezier(.3,.7,.4,1); }
.hc-pig .a-wag { animation: hc-pig-wag .45s ease-in-out; }
.hc-pig .a-ear { animation: hc-pig-eartw .5s ease-in-out; }
.hc-pig .a-wiggle { animation: hc-pig-wiggle .7s ease-in-out; }
.hc-pig .a-sniff { animation: hc-pig-sniff .18s ease-in-out 3; }
.hc-pig .a-yawn { animation: hc-pig-yawn 1.1s ease-in-out; }

@media (prefers-reduced-motion: reduce) {
    .hc-pig [data-p="float"],
    .hc-pig [data-p="breathe"],
    .hc-pig .a-blink,
    .hc-pig .a-nod,
    .hc-pig .a-sway,
    .hc-pig .a-hop,
    .hc-pig .a-wag,
    .hc-pig .a-ear,
    .hc-pig .a-wiggle,
    .hc-pig .a-sniff,
    .hc-pig .a-yawn {
        animation: none;
    }
}

/* --- Page transitions ---
   Content settles in rather than snapping, on first paint and on every
   in-app navigation. The curve is the flat-out-then-ease one Apple leans on:
   most of the movement is over almost immediately, so it reads as responsive
   rather than as a delay. Deliberately short (220ms) and deliberately tiny
   (6px): anything longer or further starts to feel like waiting.

   Only opacity and transform are animated, so it runs on the compositor and
   can't reflow the page or shift what someone is about to tap. */
.hc-main-enter {
    animation: hc-page-in 220ms cubic-bezier(0.32, 0.72, 0, 1) both;
}

@keyframes hc-page-in {
    from {
        opacity: 0;
        transform: translate3d(0, 6px, 0);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* Cross-document loads (a hard refresh, or landing from outside) cross-fade
   instead of blinking. Blazor handles in-app links itself, so this only covers
   the real page loads; browsers without it just don't animate. */
@view-transition {
    navigation: auto;
}

@media (prefers-reduced-motion: reduce) {
    .hc-main-enter {
        animation: none;
    }

    @view-transition {
        navigation: none;
    }
}

/* --- Naming the homehog --- */
.hc-pig-namer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--hc-space-3);
    text-align: center;
}

/* What the pig says back: a bubble with a tail pointing up at its snout. */
.hc-pig-speech {
    position: relative;
    max-width: 34ch;
    margin: 0;
    padding: var(--hc-space-3) var(--hc-space-4);
    background-color: var(--hc-accent-soft);
    border-radius: var(--hc-radius-lg);
    font-weight: 550;
}

.hc-pig-speech::before {
    content: "";
    position: absolute;
    top: -7px;
    left: 50%;
    transform: translateX(-50%);
    border-left: 8px solid transparent;
    border-right: 8px solid transparent;
    border-bottom: 8px solid var(--hc-accent-soft);
}

.hc-pig-namer-hello {
    margin: 0;
    font-size: var(--hc-font-size-lg);
}

.hc-pig-namer-form {
    display: flex;
    gap: var(--hc-space-2);
    width: 100%;
    max-width: 340px;
}

.hc-pig-namer-form .hc-input {
    flex: 1;
    min-width: 0;
    text-align: center;
}

/* --- Picking the accent colour ---
   Each swatch paints itself from --hc-swatch, set inline per button, so the row
   needs no per-theme CSS and adding a colour touches only themes.css and the
   ThemeColours list. The swatch shows the LIGHT base in both modes: it is a
   label for the choice, not a preview of the rendered accent, and the page
   itself is the preview the moment you click. */
.hc-theme-picker {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
}

.hc-theme-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-3);
}

.hc-swatch {
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-swatch);
    color: #ffffff;
    font-size: var(--hc-font-size-sm);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    /* The ring is drawn outside the circle so the colour stays a clean dot, and
       it is always present but transparent, so choosing doesn't shift the row. */
    outline: 2px solid transparent;
    outline-offset: 2px;
    transition: outline-color 0.15s ease, transform 0.15s ease;
}

.hc-swatch:hover:not(:disabled) {
    transform: scale(1.08);
}

.hc-swatch--on {
    outline-color: var(--hc-text-muted);
}

.hc-swatch:focus-visible {
    outline-color: var(--hc-text);
}

.hc-swatch:disabled {
    cursor: default;
}

.hc-theme-note {
    margin: 0;
}

@media (prefers-reduced-motion: reduce) {
    .hc-swatch {
        transition: none;
    }

    .hc-swatch:hover:not(:disabled) {
        transform: none;
    }
}

/* The pig leads the progress card, then steps aside on narrow screens. */
/* The pig sits inside the ring. Its artwork is bottom-heavy (the shadow sits
   near the foot of the viewBox), so it's nudged up to look centred in the
   circle rather than measured centred. */
.hc-progress-pigring .hc-pig--full {
    width: 116px;
    height: 116px;
    margin: 0;
    transform: translateY(-5px);
}

@media (max-width: 640px) {
    .hc-progress-hero {
        flex-direction: column;
        text-align: center;
    }
}

/* --- Full-screen AI analysing overlay --- */
.hc-ai-overlay {
    position: fixed;
    inset: 0;
    z-index: 400; /* over modals: nothing should interrupt the analysis */
    width: 100vw;
    height: 100dvh;
    display: grid;
    place-items: center;
    padding: var(--hc-space-5);
    background-color: color-mix(in srgb, var(--hc-bg) 88%, transparent);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    animation: hc-ai-overlay-in 0.2s ease-out;
}

@keyframes hc-ai-overlay-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.hc-ai-overlay-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--hc-space-2);
    text-align: center;
    max-width: 34ch;
}

.hc-ai-overlay-card h2 {
    margin: var(--hc-space-3) 0 0;
}

.hc-ai-overlay-card p {
    margin: 0;
}

.hc-ai-overlay-step {
    font-weight: 550;
    color: var(--hc-accent);
    min-height: 1.5em;
    animation: hc-ai-step-in 0.3s ease-out;
}

@keyframes hc-ai-step-in {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* The pig waits inside a slowly sweeping ring. */
.hc-ai-overlay-pig {
    position: relative;
    display: grid;
    place-items: center;
    width: 168px;
    height: 168px;
}

.hc-ai-overlay-pig .hc-pig--head {
    width: 116px;
    height: 116px;
}

.hc-ai-ring {
    position: absolute;
    inset: 0;
    border-radius: var(--hc-radius-full);
    border: 3px solid var(--hc-border-subtle);
    border-top-color: var(--hc-accent);
    animation: hc-ai-ring-spin 1.4s linear infinite;
}

@keyframes hc-ai-ring-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .hc-ai-overlay,
    .hc-ai-overlay-step {
        animation: none;
    }

    .hc-ai-ring {
        animation-duration: 4s;
    }
}

/* --- TA6 property information (seller questionnaire) ----------------- */

/* A reading-width column, centred in the 1100px main area. Long question
   text sprawls unpleasantly at full width; a form wants a narrower measure. */
.hc-ta6-page {
    max-width: 820px;
    margin: 0 auto;
}

/* Full-width progress strip under the page header. Styled as a quiet card so
   it belongs with the section cards below it rather than floating loose. */
.hc-ta6-progress {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
    padding: var(--hc-space-4) var(--hc-space-5);
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border-subtle);
    border-radius: var(--hc-radius-lg);
    box-shadow: var(--hc-shadow-sm);
    margin-bottom: var(--hc-space-5);
}

.hc-ta6-progress-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--hc-space-3);
}

/* Chunkier than the shared 6px bar: on this page the progress IS the story. */
.hc-ta6-progress-track {
    height: 10px;
}

.hc-ta6-progress .hc-progress-bar {
    transition: width 0.45s ease;
}

/* Finishing gets a colour shift to success, nothing louder. */
.hc-ta6-progress--complete .hc-progress-bar {
    background-color: var(--hc-success);
}

.hc-ta6-progress-done {
    color: var(--hc-success);
    font-weight: 600;
}

.hc-ta6-progress-done::before {
    content: "\2713"; /* plain tick glyph, not an emoji */
    margin-right: var(--hc-space-1);
}

.hc-ta6-skeleton-progress {
    border-radius: var(--hc-radius-lg);
    margin-bottom: var(--hc-space-5);
}

.hc-ta6-question {
    padding: var(--hc-space-5) 0;
}

.hc-ta6-question + .hc-ta6-question {
    border-top: 1px solid var(--hc-border-subtle);
}

.hc-ta6-question:first-child {
    padding-top: 0;
}

.hc-ta6-question:last-child {
    padding-bottom: 0;
}

.hc-ta6-question-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--hc-space-3);
}

.hc-ta6-question-text {
    font-weight: 600;
}

/* The save indicator's slot is always reserved, so "Saving…" appearing and
   fading never nudges the question text sideways. */
.hc-ta6-status {
    flex: none;
    min-width: 4rem;
    text-align: right;
    white-space: nowrap;
}

.hc-ta6-help {
    margin: var(--hc-space-1) 0 0;
}

.hc-ta6-options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    margin-top: var(--hc-space-3);
    max-width: 440px;
}

/* Radio-in-a-pill rows: the whole pill is the touch target, and the
   selected state reads at a glance without hunting for the dot. Equal
   flex-basis keeps Yes/No/Not known the same width. */
.hc-ta6-option {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 0;
    min-width: max-content;
    min-height: 44px;
    padding: var(--hc-space-2) var(--hc-space-4);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius-full);
    background: var(--hc-surface);
    font-size: var(--hc-font-size-sm);
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.hc-ta6-option:hover {
    border-color: var(--hc-accent);
}

.hc-ta6-option--selected {
    border-color: var(--hc-accent);
    background: var(--hc-accent-soft);
    color: var(--hc-accent);
    font-weight: 600;
}

/* The radio stays in the tree for keyboard and screen-reader flow; the pill
   itself is the visible control, so the dot is hidden rather than drawn. */
.hc-ta6-option input[type="radio"] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

/* Keyboard focus ring matching .hc-btn:focus-visible. */
.hc-ta6-option:has(input[type="radio"]:focus-visible) {
    outline: 2px solid var(--hc-accent);
    outline-offset: 2px;
}

.hc-ta6-input {
    margin-top: var(--hc-space-3);
    /* Full width of the card up to a comfortable reading measure. Without an
       explicit width these controls fall back to the browser's intrinsic
       ~20-character default, which reads as broken next to the card edge;
       everywhere else inputs get their width from .hc-form-field's column
       stretch, which these bare controls do not sit in. */
    width: 100%;
    max-width: 560px;
}

.hc-ta6-input--date {
    max-width: 220px;
}

/* Follow-up detail hangs off its trigger answer: indented behind a soft
   accent rule so the connection reads without any extra words. */
.hc-ta6-detail {
    margin-top: var(--hc-space-4);
    margin-bottom: 0;
    margin-left: var(--hc-space-2);
    padding-left: var(--hc-space-4);
    border-left: 3px solid color-mix(in srgb, var(--hc-accent) 35%, var(--hc-border-subtle));
    max-width: 560px;
}

/* Answers save themselves; this is the whole acknowledgement. Holds for a
   moment, then fades so the page never accumulates a column of "Saved"s. */
.hc-ta6-saved {
    color: var(--hc-success);
    font-weight: 600;
    animation: hc-ta6-saved-fade 2.4s ease forwards;
}

@keyframes hc-ta6-saved-fade {
    0%, 55% { opacity: 1; }
    100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .hc-ta6-saved {
        animation: none;
    }

    .hc-ta6-progress .hc-progress-bar,
    .hc-ta6-option {
        transition: none;
    }
}

/* ---------- Multi-select dropdown (searchable checkbox picker) ---------- */

.hc-multiselect {
    position: relative;
}

.hc-multiselect-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--hc-space-2);
    width: 100%;
    text-align: left;
    cursor: pointer;
}

.hc-multiselect-toggle i {
    font-size: 0.75rem;
    color: var(--hc-text-muted);
}

/* Invisible click-catcher so any outside click closes the panel. */
.hc-multiselect-backdrop {
    position: fixed;
    inset: 0;
    z-index: 39;
}

.hc-multiselect-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 40;
    padding: var(--hc-space-3);
    background: var(--hc-surface);
    border-radius: var(--hc-radius-sm);
    box-shadow: var(--hc-shadow-pop);
}

.hc-multiselect-list {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    max-height: 260px;
    overflow-y: auto;
    margin-top: var(--hc-space-3);
    padding-right: var(--hc-space-1);
}

/* ---------- What's New (release history) ---------- */

.hc-release {
    margin-bottom: var(--hc-space-4);
}

.hc-release-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--hc-space-2);
    flex-wrap: wrap;
    margin-bottom: var(--hc-space-2);
}

.hc-release-version {
    font-weight: 700;
    font-size: var(--hc-font-size-lg);
    margin-right: var(--hc-space-2);
}

.hc-release-changes {
    list-style: none;
    padding: 0;
    margin: var(--hc-space-3) 0 0;
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-3);
}

.hc-release-changes li {
    display: flex;
    align-items: baseline;
    gap: var(--hc-space-3);
}

/* The category chip: fixed width so the change text lines up in a column. */
.hc-release-chip {
    flex: 0 0 150px;
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    color: var(--hc-text-muted);
}

.hc-release-chip i {
    color: var(--hc-accent);
    margin-right: 4px;
}

@media (max-width: 640px) {
    .hc-release-changes li {
        flex-direction: column;
        gap: 2px;
    }
    .hc-release-chip {
        flex-basis: auto;
    }
}

.hc-release-dev {
    margin-top: var(--hc-space-4);
    border-top: 1px solid var(--hc-border);
    padding-top: var(--hc-space-3);
}

.hc-release-dev summary {
    cursor: pointer;
    font-size: var(--hc-font-size-sm);
    color: var(--hc-text-muted);
}

.hc-release-dev-text {
    margin-top: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    color: var(--hc-text-muted);
    white-space: pre-wrap;
}

/* ---- Password strength checker (Account pages) ---------------------------
   Markup: Components/Account/Shared/PasswordChecker.razor.
   Behaviour: js/password-checker.js toggles .is-met / .is-filled / band classes.
   Display only; PasswordPolicy.cs is what actually enforces the rules. */

.hc-pw-checker {
    /* No background of its own: it sits inside whatever card or page hosts the
       password field and should blend in, not read as a separate panel. */
    margin-top: var(--hc-space-2);
}

.hc-pw-meter {
    display: flex;
    gap: 4px;
}

.hc-pw-meter span {
    flex: 1;
    height: 6px;
    border-radius: var(--hc-radius-full);
    background: color-mix(in srgb, var(--hc-ink) 12%, transparent);
    transition: background-color 0.2s ease;
}

.hc-pw-meter.is-weak span.is-filled { background: var(--hc-danger); }
.hc-pw-meter.is-fair span.is-filled { background: var(--hc-warning); }
.hc-pw-meter.is-strong span.is-filled { background: var(--hc-success); }

.hc-pw-label {
    margin: var(--hc-space-2) 0 0;
    font-size: var(--hc-font-size-sm);
    color: var(--hc-text-muted);
}

.hc-pw-checker.is-complete .hc-pw-label {
    color: var(--hc-success);
    font-weight: 600;
}

.hc-pw-checks {
    list-style: none;
    margin: var(--hc-space-2) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 4px var(--hc-space-3);
}

.hc-pw-checks li {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    color: var(--hc-text-muted);
}

/* Two icons per row; the class on the row picks which one shows. */
.hc-pw-checks li .hc-pw-tick { display: none; color: var(--hc-success); }
.hc-pw-checks li .hc-pw-dot { color: color-mix(in srgb, var(--hc-ink) 30%, transparent); }
.hc-pw-checks li.is-met .hc-pw-tick { display: inline-block; }
.hc-pw-checks li.is-met .hc-pw-dot { display: none; }
.hc-pw-checks li.is-met { color: var(--hc-ink); }

.hc-pw-fun {
    margin: var(--hc-space-3) 0 0;
    font-size: var(--hc-font-size-sm);
    color: var(--hc-text-muted);
    font-style: italic;
}

/* ---- Badge prize preview (progress page modal) ---------------------------
   A small pig head wearing the badge's accessory, centred where the badge
   icon normally sits. */

.hc-badge-prize-pig {
    width: 96px;
    height: 96px;
    margin: 0 auto;
}

.hc-badge-prize-pig .hc-pig,
.hc-badge-prize-pig .hc-pig svg {
    width: 100%;
    height: 100%;
}

/* ---- Assistant proposal card (the chat pig's drafts) ---------------------
   Rendered under the pig's message when it has drafted a record; nothing is
   saved until Add is tapped, so the card is the review surface. */

.hc-chat-proposal {
    margin-top: var(--hc-space-2);
    padding: var(--hc-space-3);
    background: var(--hc-surface, #fff);
    border: 1px solid var(--hc-accent-soft);
    border-radius: var(--hc-radius-sm);
}

.hc-chat-proposal--done {
    opacity: 0.75;
}

.hc-chat-proposal-title {
    font-weight: 700;
    margin-bottom: var(--hc-space-2);
}

.hc-chat-proposal-fields {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px var(--hc-space-3);
    margin: 0;
    font-size: var(--hc-font-size-sm);
}

.hc-chat-proposal-fields dt {
    color: var(--hc-text-muted);
}

.hc-chat-proposal-fields dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.hc-chat-proposal-actions {
    margin-top: var(--hc-space-3);
}

.hc-chat-proposal-added {
    margin-top: var(--hc-space-2);
    color: var(--hc-success);
    font-weight: 600;
    font-size: var(--hc-font-size-sm);
}

/* ---- MoreDetails expander (add forms' collapsed optional half) ----------- */

.hc-more-details {
    margin: var(--hc-space-2) 0;
}

.hc-more-details-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--hc-space-2);
    border: none;
    background: none;
    padding: 4px 0;
    font: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    color: var(--hc-accent);
    cursor: pointer;
}

.hc-more-details-toggle i {
    font-size: 0.8em;
}

.hc-more-details-body {
    margin-top: var(--hc-space-2);
}

/* ---- Quick Add (the topbar "+" and its panel) ---------------------------- */

.hc-quickadd-btn {
    background: var(--hc-accent);
    color: #fff;
    border-radius: var(--hc-radius-full);
}

/* On a desktop the top bar is chrome, not a thumb target: the 44px minimum
   that everything else now keeps made the solid "+" circle tower over the
   search, ring, bell and avatar beside it. Header controls line up at 36
   with a mouse; on a phone they go back to full size (this rule stops at
   the same 640px the mobile shell starts at). */
@media (min-width: 641px) {
    .hc-topbar-actions .hc-icon-btn,
    .hc-topbar-actions .hc-bell {
        width: 36px;
        height: 36px;
        min-height: 36px;
    }
}

/* The shared .hc-icon-btn:hover repaints the background pale grey, which under
   a white "+" made the button all but vanish. Stay a solid accent circle and
   just deepen to the theme's hover shade. */
.hc-quickadd-btn:hover {
    background-color: var(--hc-accent-hover);
    color: #fff;
}

/* Mobile's top-right account shortcut; desktop keeps the full user menu, so
   this only appears inside the mobile media block. */
.hc-topbar-account {
    display: none;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: var(--hc-radius-full);
    color: var(--hc-text-muted);
    font-size: 24px;
}

.hc-topbar-account:hover {
    text-decoration: none;
    color: var(--hc-text);
}

/* Now the sheet's inner content: the BottomSheet owns sizing and scrolling. */
.hc-quickadd {
    text-align: left;
}

.hc-quickadd-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.hc-quickadd-head h2 {
    margin: 0;
}

.hc-quickadd-type {
    display: flex;
    gap: var(--hc-space-2);
    margin: var(--hc-space-3) 0;
}

.hc-quickadd-type .hc-input {
    flex: 1;
    min-width: 0;
}

.hc-quickadd-done {
    color: var(--hc-success);
    font-weight: 600;
    font-size: var(--hc-font-size-sm);
}

.hc-quickadd-inbox {
    margin-top: var(--hc-space-3);
    overflow-wrap: anywhere;
}

/* ---- Two-minute wins (the home page momentum nudge) ---- */

.hc-home-win {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    padding: var(--hc-space-4);
    margin-bottom: var(--hc-space-4);
    background-color: var(--hc-surface);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius-lg);
}

.hc-home-win > i {
    font-size: 20px;
    color: var(--hc-accent);
    flex-shrink: 0;
}

.hc-home-win-body {
    flex: 1;
    min-width: 0;
}

.hc-home-win-label {
    font-size: var(--hc-text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--hc-text-muted);
}

.hc-home-win-body p {
    margin: 2px 0 0;
    font-size: var(--hc-text-sm);
}

.hc-home-win-actions {
    display: flex;
    gap: var(--hc-space-2);
    flex-shrink: 0;
}

@media (max-width: 640px) {
    .hc-home-win {
        flex-wrap: wrap;
    }

    .hc-home-win-actions {
        width: 100%;
        justify-content: flex-end;
    }
}

/* ---- Capture from your pocket (tab bar +, camera button, mic, inbox keeping) ---- */

/* The tab bar's Add: a raised accent circle among flat tabs, unmistakably the
   action rather than a destination. */
.hc-tab-add {
    border: none;
    background: none;
    font: inherit;
    cursor: pointer;
    /* The accent circle defines this tab's height; the icon tabs' vertical
       padding would make the whole bar taller for nothing. */
    padding: 0;
}

.hc-tab-add-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-accent);
    color: #fff;
    box-shadow: var(--hc-shadow-pop);
    font-size: 17px;
}

.hc-tab-add:active .hc-tab-add-circle {
    background-color: var(--hc-accent-hover);
}

/* Phones only: the camera shortcut inside a dropzone. Raised above the
   zone-covering InputFile so the tap opens the camera, not the file picker. */
.hc-dropzone-camera {
    display: none;
    position: relative;
    z-index: 2;
    align-items: center;
    gap: var(--hc-space-2);
    margin-top: var(--hc-space-2);
    padding: 8px 14px;
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    font-size: var(--hc-text-sm);
    font-weight: 600;
    cursor: pointer;
}

.hc-dropzone-camera input[type="file"] {
    display: none;
}

@media (max-width: 768px) {
    .hc-dropzone-camera {
        display: inline-flex;
    }
}

/* The Quick Add mic: quiet until it's listening, then pulsing accent. */
.hc-quickadd-mic--live {
    color: var(--hc-accent);
    animation: hc-mic-pulse 1.2s ease-in-out infinite;
}

@keyframes hc-mic-pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.18); }
}

.hc-quickadd-inbox-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    margin-top: var(--hc-space-2);
}

.hc-quickadd-inbox-actions .hc-btn {
    font-size: var(--hc-text-sm);
    padding: 6px 12px;
}

/* ---- Undo on AI adds + the starter checklist ---- */

.hc-chat-proposal-undo {
    border: none;
    background: none;
    padding: 0;
    margin-left: var(--hc-space-2);
    font: inherit;
    font-weight: 600;
    color: var(--hc-accent);
    cursor: pointer;
    text-decoration: underline;
}

.hc-chat-proposal-undone {
    color: var(--hc-text-muted);
}

/* Which property the home page is about, beside the Customise button. */
.hc-home-header-actions {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    flex-wrap: wrap;
}

.hc-property-switch {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    color: var(--hc-text-muted);
}

.hc-property-switch select {
    min-width: 160px;
    max-width: 260px;
}

/* The two nudge cards ride together: side by side once there is room, stacked
   below that. auto-fit rather than a fixed pair, because either card can hide
   itself and a fixed 1fr 1fr would leave the survivor at half width. */
.hc-home-nudges {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
    gap: var(--hc-space-4);
    /* Stretch, not start: two cards side by side that end at different
       heights read as one broken card, however tidy each is on its own. */
    align-items: stretch;
}

.hc-starter {
    margin-bottom: var(--hc-space-4);
}

.hc-home-nudges .hc-starter {
    margin-bottom: 0;
}

/* Title takes the slack so the count and the close button stay together on the
   right. space-between used to leave "2 of 6 done" stranded mid-row. */
.hc-starter-head {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
}

.hc-starter-head .hc-card-title {
    flex: 1;
    min-width: 0;
    margin: 0;
}

.hc-starter-head .hc-text-sm {
    white-space: nowrap;
}

/* One line of preamble under a heading needs no extra gap of its own. */
.hc-starter > p {
    margin: var(--hc-space-1) 0 0;
}

.hc-starter-list {
    list-style: none;
    margin: var(--hc-space-3) 0 0;
    padding: 0;
    display: grid;
    gap: 6px;
}

.hc-starter-list a {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    color: inherit;
}

.hc-starter-list .hc-starter-done {
    color: var(--hc-text-muted);
}

/* Strike the words only; a line through the tick reads as "un-ticked". */
.hc-starter-list .hc-starter-done span {
    text-decoration: line-through;
}

.hc-starter-list i {
    width: 18px;
    text-align: center;
    color: var(--hc-accent);
}

.hc-starter-list .hc-starter-done i {
    color: var(--hc-success);
}

/* ---- Native sign-in card ---- */

.hc-signin-card {
    width: min(380px, 92vw);
    text-align: left;
}

.hc-signin-card h1 {
    font-size: var(--hc-text-xl, 22px);
    margin: 0 0 var(--hc-space-3);
}

.hc-signin-brand {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-4);
    font-weight: 800;
    color: var(--hc-accent);
}

.hc-signin-brand img {
    width: 28px;
    height: 28px;
}

.hc-signin-card .hc-btn--block + .hc-btn--block {
    margin-top: var(--hc-space-2);
}

/* ---- Command palette (SearchPalette) ---- */

/* Sits higher than the standard modal position so results growing and
   shrinking don't bounce the input around the screen centre. */
.hc-search-palette {
    top: 10vh;
    transform: translate(-50%, 0);
    width: min(560px, calc(100vw - 32px));
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    padding: 12px;
}

/* Phones: search is a full-screen state (the Spotify/YouTube pattern), input
   pinned top by the keyboard, results filling the rest. */
@media (max-width: 640px) {
    .hc-search-palette {
        inset: 0;
        top: 0;
        left: 0;
        transform: none;
        width: 100vw;
        height: 100dvh;
        max-height: 100dvh;
        border-radius: 0;
        padding-top: max(12px, env(safe-area-inset-top));
    }

    .hc-search-results {
        flex: 1;
        max-height: none;
    }
}

.hc-search-inputrow {
    display: flex;
    align-items: center;
    gap: 10px;
}

.hc-search-inputrow > i {
    color: var(--hc-text-muted);
}

.hc-search-input {
    flex: 1;
    border: none;
    box-shadow: none;
    font-size: 1.05rem;
}

.hc-search-input:focus {
    outline: none;
    box-shadow: none;
}

.hc-search-results {
    overflow-y: auto;
    margin-top: 8px;
    border-top: 1px solid var(--hc-border);
    padding-top: 8px;
}

.hc-search-group {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--hc-text-muted);
    padding: 8px 10px 4px;
}

.hc-search-hit {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: 10px;
    color: inherit;
    text-decoration: none;
}

.hc-search-hit i {
    width: 18px;
    text-align: center;
    color: var(--hc-accent);
}

.hc-search-hit--selected {
    background: var(--hc-surface-sunken);
}

.hc-search-hit-title {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hc-search-hit-sub {
    color: var(--hc-text-muted);
    font-size: 0.85rem;
}

.hc-search-empty {
    padding: 16px 10px 8px;
}

/* ---- This month at home (SeasonalCard) ---- */

.hc-seasonal-list {
    list-style: none;
    margin: var(--hc-space-3) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Wraps whenever the actions no longer fit, which now happens on a wide screen
   too: side by side, each nudge card is about half the page. */
.hc-seasonal-item {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 12px;
}

.hc-seasonal-item > i {
    color: var(--hc-accent);
    width: 20px;
    text-align: center;
    margin-top: 3px;
}

.hc-seasonal-body {
    flex: 1;
    min-width: 200px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.hc-seasonal-title {
    font-weight: 600;
}

.hc-seasonal-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* Stack the action under the text on narrow phones instead of squeezing it. */
@media (max-width: 480px) {
    .hc-seasonal-item {
        flex-wrap: wrap;
    }

    .hc-seasonal-actions {
        margin-left: 32px;
    }
}

/* ---- Home health (PropertyHealthCard) ---- */

.hc-health-summary {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 12px;
}

/* The whole summary is the disclosure control, so the target is the card row
   rather than a chevron the size of a fingernail. Styled as a plain row, not a
   button: it is a card people read, and only incidentally something to tap. */
.hc-health-toggle {
    display: flex;
    align-items: center;
    gap: 16px;
    width: 100%;
    padding: 0;
    border: none;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.hc-health-summary-text {
    flex: 1;
    min-width: 0;
}

.hc-health-summary-text p {
    margin: 2px 0 0;
}

.hc-health-chevron {
    flex-shrink: 0;
    width: 32px;
    color: var(--hc-text-muted);
    text-align: right;
}

.hc-health-toggle:hover .hc-health-chevron {
    color: var(--hc-text);
}

/* The ring is a conic gradient driven by --health-pct; the inner disc masks
   it back to a ring so no SVG is needed. */
.hc-health-ring {
    width: 72px;
    height: 72px;
    flex-shrink: 0;
    border-radius: 50%;
    background: conic-gradient(var(--health-colour) calc(var(--health-pct) * 1%), var(--hc-surface-sunken) 0);
    display: flex;
    align-items: center;
    justify-content: center;
}

.hc-health-ring span {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--hc-surface);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 1.15rem;
}

.hc-health-band {
    font-weight: 600;
    font-size: 1.05rem;
}

/* Add-a-supplier without leaving the job. Inset and tinted so it reads as a
   panel belonging to the dropdown above it rather than part of the form it is
   sitting inside, which it very much is not. */
.hc-supplier-add {
    margin-top: var(--hc-space-2);
    padding: var(--hc-space-3);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius);
    background: var(--hc-surface-sunken);
}

.hc-supplier-add-title {
    font-weight: 600;
    margin-bottom: var(--hc-space-1);
}

/* The letting card on a rented-out property page: who is in, then the row of
   jobs that only exist because it is let. The action row wraps rather than
   scrolls, because a landlord on a phone should see all four at once. */
.hc-letting-tenants {
    list-style: none;
    margin: 0 0 var(--hc-space-3);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
}

.hc-letting-tenants li {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    flex-wrap: wrap;
}

.hc-letting-tenants a {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.hc-letting-tenant {
    font-weight: 600;
}

.hc-letting-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
}

.hc-health-factors {
    list-style: none;
    margin: 14px 0 0;
    padding: 14px 0 0;
    border-top: 1px solid var(--hc-border);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.hc-health-factors li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.hc-health-factors li > i {
    margin-top: 3px;
}

.hc-health-pass > i {
    color: var(--hc-success);
}

.hc-health-miss > i {
    color: var(--hc-warning);
}

.hc-health-factors li > div {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.hc-health-factor-title {
    font-weight: 600;
}

.hc-health-factors .hc-btn {
    flex-shrink: 0;
}

/* The drafted warranty claim letter: monospace-adjacent readability without
   pretending to be code. */
.hc-claim-letter {
    font-size: 0.9rem;
    line-height: 1.5;
    white-space: pre-wrap;
}

/* The manual helper strip on the appliance page. */
.hc-manual-helper {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.hc-manual-helper .hc-form-actions {
    margin: 0;
    flex-shrink: 0;
}

/* ---- BottomSheet: the one dialog surface ----------------------------- */

/* Desktop: the familiar centred dialog, flex-positioned by the backdrop so
   tall content grows down rather than off-centre. */
.hc-sheet-backdrop {
    position: fixed;
    inset: 0;
    background-color: rgba(22, 35, 58, 0.45);
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--hc-space-4);
}

.hc-sheet {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(520px, 100%);
    max-height: min(85vh, 720px);
    background-color: var(--hc-surface);
    border-radius: var(--hc-radius);
    box-shadow: var(--hc-shadow-pop);
}

.hc-sheet-backdrop--fullscreen .hc-sheet {
    width: min(680px, 100%);
}

.hc-sheet-grip {
    display: none;
}

.hc-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--hc-space-3);
    padding: var(--hc-space-4) var(--hc-space-5) 0;
}

.hc-sheet-head h2 {
    margin: 0;
    font-size: 1.15rem;
}

/* Untitled sheets still need a way out that isn't a gesture. */
.hc-sheet-close {
    position: absolute;
    top: var(--hc-space-3);
    right: var(--hc-space-3);
    z-index: 1;
}

.hc-sheet-body {
    padding: var(--hc-space-4) var(--hc-space-5) var(--hc-space-5);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Action sheet: a short list of big tappable choices. */
.hc-sheet-option {
    display: flex;
    width: 100%;
    align-items: center;
    gap: var(--hc-space-3);
    padding: 14px var(--hc-space-3);
    border: none;
    background: none;
    border-radius: var(--hc-radius);
    font: inherit;
    font-size: 1rem;
    text-align: left;
    cursor: pointer;
    color: inherit;
}

.hc-sheet-option:hover {
    background-color: var(--hc-surface-sunken);
}

.hc-sheet-option > i {
    width: 22px;
    text-align: center;
    color: var(--hc-accent);
}

.hc-sheet-option--danger,
.hc-sheet-option--danger > i {
    color: var(--hc-danger);
}

.hc-sheet-option-sub {
    display: block;
    font-size: 0.85rem;
    color: var(--hc-text-muted);
}

.hc-sheet-option--danger .hc-sheet-option-sub {
    color: var(--hc-text-muted);
}

/* Phones: the sheet rises from the bottom into thumb range. */
@media (max-width: 640px) {
    .hc-sheet-backdrop {
        align-items: flex-end;
        padding: 0;
    }

    .hc-sheet {
        width: 100%;
        max-height: calc(100dvh - 44px);
        border-radius: 20px 20px 0 0;
        padding-bottom: env(safe-area-inset-bottom);
        animation: hc-sheet-up 0.22s ease-out;
        /* The drag gesture moves the sheet with transform; keep it snappy. */
        transition: transform 0.18s ease-out;
        touch-action: pan-y;
    }

    .hc-sheet-grip {
        display: flex;
        justify-content: center;
        padding: 10px 0 2px;
        flex-shrink: 0;
    }

    .hc-sheet-grip span {
        width: 40px;
        height: 4px;
        border-radius: 2px;
        background-color: var(--hc-border);
    }

    /* Full-screen takeover: forms and detail views own the whole screen. The
       grip hides because swiping a page away feels wrong; the X closes it. */
    .hc-sheet-backdrop--fullscreen .hc-sheet {
        height: 100dvh;
        max-height: 100dvh;
        border-radius: 0;
        animation: hc-sheet-up 0.22s ease-out;
    }

    .hc-sheet-backdrop--fullscreen .hc-sheet-grip {
        display: none;
    }

    .hc-sheet-backdrop--fullscreen .hc-sheet-head {
        padding-top: max(var(--hc-space-4), env(safe-area-inset-top));
    }
}

@keyframes hc-sheet-up {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
}

/* ---- Mobile containment fixes (from real-device review) -------------- */

@media (max-width: 640px) {
    /* Buttons carry nowrap for tidy desktop rows, but on a phone a long
       label ("Ask the homehog about it", a badge's accessory offer) must
       wrap inside its card, never escape it. */
    .hc-card .hc-btn,
    .hc-modal .hc-btn,
    .hc-sheet .hc-btn {
        white-space: normal;
        max-width: 100%;
        text-align: center;
    }

    /* The manual helper stacks: text above, actions below, full width. */
    .hc-manual-helper {
        flex-direction: column;
        align-items: stretch;
    }

    .hc-manual-helper .hc-form-actions {
        flex-wrap: wrap;
    }

    /* The grip, swipe and backdrop already close a sheet on a phone; the X
       is desktop furniture. Full-screen takeovers keep it, there the X is
       the only way out. */
    .hc-sheet-backdrop:not(.hc-sheet-backdrop--fullscreen) .hc-sheet-head .hc-icon-btn,
    .hc-sheet-backdrop:not(.hc-sheet-backdrop--fullscreen) .hc-sheet-close {
        display: none;
    }
}

/* Belt and braces for every container on every screen: nothing inside a
   card, dialog or sheet may widen it past its box. */
.hc-card,
.hc-modal,
.hc-sheet {
    overflow-wrap: anywhere;
}

/* ---- Notifications as a top sheet on phones -------------------------- */

/* Desktop keeps the anchored dropdown; the panel itself scrolls, so the
   inner scroll wrapper is transparent there. */
.hc-bell-scroll {
    display: contents;
}

.hc-bell-grip {
    display: none;
}

@media (max-width: 640px) {
    .hc-bell-panel {
        position: fixed;
        inset: 0 0 auto 0;
        top: 0;
        width: 100%;
        max-width: none;
        max-height: none;
        overflow: visible;
        display: flex;
        flex-direction: column;
        border: none;
        border-radius: 0 0 20px 20px;
        padding-top: max(var(--hc-space-2), env(safe-area-inset-top));
        animation: hc-topsheet-down 0.22s ease-out;
        transition: transform 0.18s ease-out;
        touch-action: pan-y;
        z-index: 301;
    }

    /* The list scrolls inside the sheet, capped so the sheet stays a sheet. */
    .hc-bell-scroll {
        display: block;
        overflow-y: auto;
        overscroll-behavior: contain;
        max-height: min(60dvh, 480px);
    }

    /* The grip sits at the BOTTOM of a top sheet, where the closing drag starts. */
    .hc-bell-grip {
        display: flex;
        justify-content: center;
        padding: 6px 0 10px;
        flex-shrink: 0;
    }

    .hc-bell-backdrop {
        z-index: 300;
    }
}

@keyframes hc-topsheet-down {
    from { transform: translateY(-100%); }
    to { transform: translateY(0); }
}

/* ---- Drop zones on phones: a tap row, not drag-and-drop theatre ------- */

.hc-dropzone-mobile-only {
    display: none;
}

@media (max-width: 640px) {
    .hc-dropzone-desktop-only {
        display: none;
    }

    .hc-dropzone-mobile-only {
        display: block;
    }

    /* Compact row: solid hairline instead of the dashed invitation, icon and
       wording side by side, camera button unchanged beside them. */
    .hc-dropzone {
        flex-direction: row;
        justify-content: flex-start;
        text-align: left;
        gap: var(--hc-space-3);
        padding: var(--hc-space-3) var(--hc-space-4);
        border: 1px solid var(--hc-border);
    }

    .hc-dropzone i {
        font-size: 1.25rem;
    }
}

/* --- Stepped job flow (maintenance and home improvement) ---
   One panel showing one step at a time, with a rail across the top so progress
   and the way back are both always visible. */

.hc-stage-rail {
    display: flex;
    align-items: flex-start;
    gap: var(--hc-space-1);
    margin-bottom: var(--hc-space-4);
    overflow-x: auto;
    /* A rail that scrolls sideways on a narrow phone rather than wrapping into
       two ragged lines, which reads as two rails. */
    scrollbar-width: none;
}

.hc-stage-rail::-webkit-scrollbar {
    display: none;
}

.hc-stage-step {
    display: flex;
    flex: 1 1 0;
    min-width: 72px;
    flex-direction: column;
    align-items: center;
    gap: var(--hc-space-2);
    padding: var(--hc-space-2) var(--hc-space-1);
    border: 0;
    border-radius: var(--hc-radius-sm);
    background: none;
    color: var(--hc-text-muted);
    font-family: inherit;
    font-size: var(--hc-font-size-xs);
    font-weight: 600;
    text-align: center;
    cursor: pointer;
}

.hc-stage-step:disabled {
    cursor: default;
    opacity: 0.55;
}

.hc-stage-step:not(:disabled):hover {
    background-color: var(--hc-surface-sunken);
}

.hc-stage-dot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 2px solid var(--hc-border);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    font-size: var(--hc-font-size-xs);
    line-height: 1;
}

.hc-stage-step--done .hc-stage-dot {
    border-color: var(--hc-success);
    background-color: var(--hc-success-soft);
    color: var(--hc-success);
}

.hc-stage-step--current {
    color: var(--hc-text);
}

.hc-stage-step--current .hc-stage-dot {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
}

.hc-stage-label {
    line-height: 1.2;
    hyphens: none;
}

@media (max-width: 640px) {
    /* Five steps will not fit a phone. Let them keep their own width and let
       the rail scroll: squeezing them breaks "Permissions" mid-word, and a
       part-visible fifth step is what tells you there is more to see. */
    .hc-stage-step {
        flex: 0 0 auto;
        min-width: 84px;
    }
}

.hc-work-panel-head h2 {
    margin: 0 0 var(--hc-space-1);
}

.hc-work-panel-head p {
    margin: 0 0 var(--hc-space-4);
}

/* Shown only when someone has stepped back to a decision already made. */
.hc-work-panel-note {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    padding: var(--hc-space-2) var(--hc-space-3);
    margin-bottom: var(--hc-space-4);
    border-radius: var(--hc-radius-sm);
    background-color: var(--hc-surface-sunken);
    color: var(--hc-text-muted);
    font-size: var(--hc-font-size-sm);
}

.hc-work-panel-note button {
    margin-left: auto;
}

.hc-work-panel-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--hc-space-2);
    margin-top: var(--hc-space-4);
}

/* A fork in the flow: what the option is, and what it does. */
.hc-work-choice {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    width: 100%;
    padding: var(--hc-space-3) var(--hc-space-4);
    margin-bottom: var(--hc-space-2);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.hc-work-choice:not(:disabled):hover {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
}

.hc-work-choice:disabled {
    cursor: default;
    opacity: 0.55;
}

.hc-work-choice--selected {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
}

.hc-work-choice-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
}

.hc-work-choice-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.hc-work-choice-title {
    display: flex;
    align-items: center;
    gap: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    font-weight: 650;
}

.hc-work-choice-text {
    color: var(--hc-text-muted);
    font-size: var(--hc-font-size-sm);
    line-height: var(--hc-line-height);
}

.hc-work-choice-go {
    margin-left: auto;
    color: var(--hc-text-muted);
}

@media (max-width: 640px) {
    /* The chevron is decoration once the whole card is the target, and the
       space it takes is better spent on the description. */
    .hc-work-choice-go {
        display: none;
    }

    .hc-work-panel-note button {
        margin-left: 0;
    }
}

/* Search results when picking a supplier inside the job flow. Rows, not a
   dropdown, so the reason each one is being offered can travel with it. */
.hc-supplier-results {
    display: flex;
    flex-direction: column;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-3);
}

.hc-supplier-result {
    display: flex;
    align-items: center;
    gap: var(--hc-space-3);
    width: 100%;
    padding: var(--hc-space-3);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius-sm);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.hc-supplier-result:not(:disabled):hover {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
}

.hc-supplier-result-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.hc-supplier-result-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    font-size: var(--hc-font-size-sm);
    font-weight: 650;
}

.hc-supplier-result-go {
    margin-left: auto;
    color: var(--hc-text-muted);
}

/* What the job has picked up so far, under the step being worked on. */
.hc-work-summary {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-3);
    padding: var(--hc-space-3) var(--hc-space-4);
    margin-bottom: var(--hc-space-4);
    border-radius: var(--hc-radius);
    background-color: var(--hc-surface-sunken);
    font-size: var(--hc-font-size-sm);
}

.hc-work-summary-facts {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hc-space-4);
    min-width: 0;
}

.hc-work-summary-facts i {
    margin-right: var(--hc-space-1);
    color: var(--hc-accent);
}

.hc-work-summary > a {
    margin-left: auto;
}

@media (max-width: 640px) {
    .hc-work-summary > a {
        margin-left: 0;
        width: 100%;
        justify-content: center;
    }
}

/* The "why are you changing supplier?" panel. Chips first because the four
   common answers should cost one tap; the box is for everything else. */
.hc-reason-panel {
    margin-bottom: var(--hc-space-4);
}

.hc-reason-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--hc-space-2);
    margin-bottom: var(--hc-space-3);
}

.hc-chip {
    padding: var(--hc-space-2) var(--hc-space-3);
    border: 1px solid var(--hc-border);
    border-radius: var(--hc-radius-full);
    background-color: var(--hc-surface);
    color: var(--hc-text);
    font-family: inherit;
    font-size: var(--hc-font-size-sm);
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.hc-chip:hover {
    border-color: var(--hc-accent);
}

.hc-chip--on {
    border-color: var(--hc-accent);
    background-color: var(--hc-accent-soft);
    color: var(--hc-accent);
}

/* --- Field labelling: what's optional, and what a word means ---
   Required fields have always carried a "*". That only helps someone who
   already knows the convention, so the other half is now said out loud. */

.hc-optional {
    margin-left: var(--hc-space-2);
    color: var(--hc-text-muted);
    font-size: var(--hc-font-size-xs);
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
}

/* One line under a field, for the ones with a name only a conveyancer would
   recognise. Sits between the input and the validation message. */
.hc-field-hint {
    color: var(--hc-text-muted);
    font-size: var(--hc-font-size-xs);
    line-height: var(--hc-line-height);
}
