@import 'Olympus.Web.Client.gjxdifusu6.bundle.scp.css';

/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-3fs4yjkc0x] {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    /* dvh tracks the *actual* visible viewport, shrinking when the on-screen keyboard opens
       (paired with interactive-widget=resizes-content in App.razor for Chromium). Without this,
       the page stayed at the pre-keyboard 100vh height, so the composer at the bottom of a chat
       thread -- sized off this container via flex/height:100% -- ended up hidden behind the
       keyboard instead of sitting just above it. Plain 100vh above is the fallback for browsers
       that don't support dvh at all. */
    min-height: 100dvh;
}

main[b-3fs4yjkc0x] {
    flex: 1;
    min-height: 0;
    padding-bottom: 4.5rem;
}

@media (min-width: 768px) {
    .page[b-3fs4yjkc0x] {
        flex-direction: row;
    }

    main[b-3fs4yjkc0x] {
        flex: 1;
        padding-bottom: 0;
        margin-left: 240px;
    }
}

#blazor-error-ui[b-3fs4yjkc0x] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-3fs4yjkc0x] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
.app-nav[b-f6w54ng8b9] {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    background: color-mix(in srgb, var(--surface) 42%, transparent);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border-top: 1px solid var(--line);
    box-shadow: var(--e3);
    padding-bottom: env(safe-area-inset-bottom);
}

.app-nav__brand-row[b-f6w54ng8b9] {
    display: none;
}

.app-nav__items[b-f6w54ng8b9] {
    /* Drives the indicator's per-item step. Keep in sync with the NavLink count below — the
       indicator has no way to measure the items, so a fourth link silently mis-steps it. */
    --nav-item-count: 3;
    position: relative;
    display: flex;
    flex-direction: row;
    justify-content: space-around;
    align-items: stretch;
    height: 4.5rem;
}

.app-nav__indicator[b-f6w54ng8b9] {
    position: absolute;
    top: 50%;
    left: calc((100% / var(--nav-item-count)) * var(--nav-active-index, 0) + (100% / var(--nav-item-count) / 2));
    width: 3.5rem;
    height: 3rem;
    border-radius: var(--r-ctl);
    /* Brand-tinted pill (rev. 08-22b: was neutral --fill). --brand-soft rather than a solid
       --brand, which the doc's "retint it to --brand" reads as at first glance: the glyph on
       top of this pill is itself --brand now, so a solid fill would swallow it. --brand-soft
       is the token whose stated job is the selected tint, and it keeps the pair legible in
       both themes. The old metallic inset glow stays gone.

       The motion is what's kept, not the material — and with mobile labels hidden this is the
       only active-state signal down here besides icon colour, so it is load-bearing. If it is
       ever removed, mobile labels come back in the same change. */
    background: var(--brand-soft);
    pointer-events: none;
    transform: translate(-50%, -50%);
    transition: left 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ::deep is mandatory here, not stylistic. NavLink is a component that renders its own <a>, and
   CSS isolation stamps the b-* scope attribute only onto plain elements written in this file —
   the anchor never gets one. A bare `.app-nav__item` compiles to `.app-nav__item[b-…]` and
   matches nothing at all. ::deep pins the scope to .app-nav__items (a real div here) and leaves
   the item selector unscoped, which is what actually reaches the anchor. Same applies to any
   future rule targeting a NavLink; .app-nav__icon/__label are spans in this file, so they scope
   normally and must stay un-::deep'd. */
.app-nav__items[b-f6w54ng8b9]  .app-nav__item {
    position: relative;
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    /* --ink-2, not --ink-3 (rev. 08-22b): an inactive nav glyph is a control you have to be
       able to find, and at the old --ink-3 (2.6:1) it was the single most-reported "can't
       see it". */
    color: var(--ink-2);
    text-decoration: none;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    transition: color 0.15s ease;
}

/* The active nav item is an action state, so it takes --brand (rev. 08-22b: was --ink). */
.app-nav__items[b-f6w54ng8b9]  .app-nav__item.active {
    color: var(--brand);
}

.app-nav__label[b-f6w54ng8b9] {
    display: none;
}

/* 24px, per the reference's tab bar — up from 1.25rem. */
.app-nav__icon[b-f6w54ng8b9] {
    display: flex;
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
}

.app-nav__icon svg[b-f6w54ng8b9] {
    width: 100%;
    height: 100%;
    fill: currentColor;
}

/* Hidden on mobile — the bottom bar is a 4.5rem strip with three touch targets already, and
   squeezing an account control in would push every one of them under the HIG minimum. The
   Profile page carries the mobile sign-out instead. */
.app-nav__auth[b-f6w54ng8b9] {
    display: none;
}

@media (min-width: 768px) {
    .app-nav[b-f6w54ng8b9] {
        top: 0;
        bottom: 0;
        width: 240px;
        height: 100vh;
        flex-direction: column;
        border-top: none;
        border-right: 1px solid var(--line);
        box-shadow: var(--e2);
        padding: 1.5rem 0;
    }

    .app-nav__brand-row[b-f6w54ng8b9] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        padding: 0 1.5rem 1.5rem;
    }

    .app-nav__brand[b-f6w54ng8b9] {
        color: var(--ink);
        font-weight: 700;
        font-size: 1.1rem;
        letter-spacing: 0.01em;
        text-decoration: none;
    }

    .app-nav__items[b-f6w54ng8b9] {
        --nav-item-h: 3rem;
        --nav-item-gap: 0.25rem;
        flex-direction: column;
        align-items: stretch;
        height: auto;
        gap: var(--nav-item-gap);
    }

    .app-nav__indicator[b-f6w54ng8b9] {
        top: 0;
        left: 0;
        width: 100%;
        height: var(--nav-item-h);
        border-radius: var(--r-ctl);
        background: var(--brand-soft);
        box-shadow: inset 2px 0 0 var(--brand);
        transform: translateY(calc(var(--nav-active-index, 0) * (var(--nav-item-h) + var(--nav-item-gap))));
        transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* flex:none is load-bearing, not tidying. The base rule sets `flex: 1`, whose `flex-basis: 0%`
       wins over `height` on a column container's main axis — the rows would collapse to
       min-content while .app-nav__indicator stayed a hard 3rem stepping by 3.25rem, so the pill
       and the items drift apart. Sizing both from --nav-item-h is what keeps them locked. */
    .app-nav__items[b-f6w54ng8b9]  .app-nav__item {
        flex: none;
        height: var(--nav-item-h);
        flex-direction: row;
        justify-content: flex-start;
        gap: 0.75rem;
        padding: 0 1.5rem;
        font-size: 0.95rem;
        font-weight: 500;
        letter-spacing: normal;
        text-transform: none;
    }

    .app-nav__label[b-f6w54ng8b9] {
        display: inline;
    }

    /* margin-top:auto against the 100vh sidebar pins this to the bottom, clear of the nav items
       regardless of how many there are. */
    .app-nav__auth[b-f6w54ng8b9] {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 0.4rem;
        margin-top: auto;
        padding: 1rem 1.5rem 0;
        border-top: 1px solid var(--line);
    }

    .app-nav__user[b-f6w54ng8b9] {
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 0.8rem;
        color: var(--ink-2);
    }

    .app-nav__auth-form[b-f6w54ng8b9] {
        margin: 0;
    }

    .app-nav__auth-btn[b-f6w54ng8b9] {
        display: inline-flex;
        align-items: center;
        padding: 0;
        border: none;
        background: none;
        font: inherit;
        font-size: 0.8rem;
        font-weight: 500;
        color: var(--ink);
        text-decoration: none;
        cursor: pointer;
        transition: color 0.15s ease;
    }

    .app-nav__auth-btn:hover[b-f6w54ng8b9] {
        color: var(--ink-2);
    }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-a67dqllm1z],
.components-reconnect-repeated-attempt-visible[b-a67dqllm1z],
.components-reconnect-failed-visible[b-a67dqllm1z],
.components-pause-visible[b-a67dqllm1z],
.components-resume-failed-visible[b-a67dqllm1z],
.components-rejoining-animation[b-a67dqllm1z] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-retrying[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-failed[b-a67dqllm1z],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-a67dqllm1z] {
    display: block;
}


#components-reconnect-modal[b-a67dqllm1z] {
    background: var(--surface);
    color: var(--ink);
    width: 20rem;
    margin: 20vh auto;
    padding: var(--s8);
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    box-shadow: var(--e2);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-a67dqllm1z 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-a67dqllm1z 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-a67dqllm1z 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-a67dqllm1z]::backdrop {
    background-color: var(--scrim);
    animation: components-reconnect-modal-fadeInOpacity-b-a67dqllm1z 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-a67dqllm1z {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-a67dqllm1z {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-a67dqllm1z {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-a67dqllm1z] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-a67dqllm1z] {
    margin: 0;
    text-align: center;
}

/* The .btn-primary recipe, restated: this markup is Blazor's reserved reconnect-UI contract
   and can't take our classes. */
#components-reconnect-modal button[b-a67dqllm1z] {
    border: 1px solid var(--brand);
    background: var(--brand);
    color: var(--on-brand);
    font-weight: 600;
    padding: 4px 24px;
    border-radius: var(--r-ctl);
    cursor: pointer;
}

    #components-reconnect-modal button:hover[b-a67dqllm1z] {
        background: color-mix(in srgb, var(--brand) 86%, var(--ink));
        border-color: color-mix(in srgb, var(--brand) 86%, var(--ink));
    }

.components-rejoining-animation[b-a67dqllm1z] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-a67dqllm1z] {
        position: absolute;
        /* --ink, not --live: reconnecting is not presence. This is where this animation and
           MapLoadingOverlay's visually identical ripple deliberately part ways — that one
           resolves into the user's own live location dot, so it stays cyan. */
        border: 3px solid var(--ink);
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-a67dqllm1z 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-a67dqllm1z] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-a67dqllm1z {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Landing.razor.rz.scp.css */
/* Marketing surface, but it lives inside the app, so it follows the same never-list: no
   gradients on UI surfaces, no glows, one primary action. Display-size type is the one place
   this page is allowed to be louder than the product screens. */

.landing-hero[b-ozp3xq3a0h] {
    min-height: calc(100vh - 3.5rem);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3rem;
    padding: 3rem var(--s8);
}

.landing-content[b-ozp3xq3a0h] {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    max-width: 640px;
}

/* The .chip recipe at --t-label metrics. */
.landing-badge[b-ozp3xq3a0h] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: fit-content;
    padding: 5px var(--s3);
    border-radius: var(--r-pill);
    background: var(--fill);
    color: var(--ink);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Was gradient-filled via background-clip. */
.landing-title[b-ozp3xq3a0h] {
    font-size: clamp(2.5rem, 6vw, 4rem);
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.03em;
    margin: 0;
    color: var(--ink);
}

/* Two-tone headline: the emphasised phrase steps down the neutral ramp rather than changing
   hue. There is no accent colour to reach for, and --live is not available for decoration. */
.landing-accent[b-ozp3xq3a0h] {
    color: var(--ink-2);
}

.landing-subtitle[b-ozp3xq3a0h] {
    font-size: 1.125rem;
    line-height: 1.7;
    color: var(--ink-2);
    margin: 0;
    max-width: 480px;
}

.landing-actions[b-ozp3xq3a0h] {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 0.5rem;
}

/* Keep the class names — same reasoning as .crystal-panel: the material is gone, the markup
   stays put. These are .btn-primary / .btn-ghost at landing scale. */
.btn-primary-crystal[b-ozp3xq3a0h] {
    padding: 0.75rem var(--s8);
    border-radius: var(--r-ctl);
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    border: 1px solid var(--brand);
    background: var(--brand);
    color: var(--on-brand);
    transition: background-color 0.18s ease, border-color 0.18s ease;
}

.btn-primary-crystal:hover[b-ozp3xq3a0h] {
    background: color-mix(in srgb, var(--brand) 86%, var(--ink));
    border-color: color-mix(in srgb, var(--brand) 86%, var(--ink));
    color: var(--on-brand);
}

.btn-ghost-crystal[b-ozp3xq3a0h] {
    padding: 0.75rem var(--s8);
    border-radius: var(--r-ctl);
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink);
    transition: background-color 0.18s ease;
}

.btn-ghost-crystal:hover[b-ozp3xq3a0h] {
    color: var(--ink);
    background: var(--fill);
}

.landing-stats[b-ozp3xq3a0h] {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.stat-card[b-ozp3xq3a0h] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 1.25rem 1.75rem;
    min-width: 140px;
    border-radius: var(--r-card);
    background: var(--surface);
    border: 1px solid var(--line);
}

.stat-value[b-ozp3xq3a0h] {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--ink);
}

.stat-label[b-ozp3xq3a0h] {
    font-size: 0.8rem;
    color: var(--ink-2);
    letter-spacing: 0.04em;
}
/* /Components/Pages/Profile.razor.rz.scp.css */
/* The hero (avatar, name, bio, actions) plus the account-details panel. The mock stats/tags/
   progress sections that used to fill out this page were removed with the bio+avatar pass —
   nothing backed them, and showing fabricated numbers is worse than showing less. Reintroduce
   them if a real gamification feature (streaks, tokens) lands to back them. */

.profile-page[b-ess5th4qpi] {
    max-width: 900px;
    margin: 0 auto;
    padding: var(--s8) 1.25rem 3rem;
}

/* Hero */
.hero[b-ess5th4qpi] {
    position: relative;
    border-radius: var(--r-card);
    padding: 36px var(--s8);
    margin-bottom: var(--s5);
    background: var(--surface);
    border: 1px solid var(--line);
    box-shadow: var(--e1);
    overflow: hidden;
    display: flex;
    align-items: center;
    gap: 26px;
    flex-wrap: wrap;
}

/* The swept shine that used to cross the hero (.hero::before) is gone — a gradient on a UI
   surface, which the never-list rules out. */

/* Same material as .chat-avatar in app.css, at hero scale: a flat identity fill with white
   initials, hashed to --ava-1..6 by Profile.razor's AvaFillIndex (mirrors pin-avatars.js's
   avaFillFor so a person's colour will still match once avatars reach the map). A real photo
   (.avatar img) draws over the fill the same way .chat-avatar img does. */
.avatar[b-ess5th4qpi] {
    position: relative;
    width: 92px;
    height: 92px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--ava-1);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--on-ava);
}

.avatar img[b-ess5th4qpi] {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
}

.avatar--a1[b-ess5th4qpi] { background: var(--ava-1); }
.avatar--a2[b-ess5th4qpi] { background: var(--ava-2); }
.avatar--a3[b-ess5th4qpi] { background: var(--ava-3); }
.avatar--a4[b-ess5th4qpi] { background: var(--ava-4); }
.avatar--a5[b-ess5th4qpi] { background: var(--ava-5); }
.avatar--a6[b-ess5th4qpi] { background: var(--ava-6); }

.hero-info[b-ess5th4qpi] {
    position: relative;
    z-index: 1;
}

/* Was gradient-filled text via background-clip. Flat --ink at the --t-title step. */
.hero-name[b-ess5th4qpi] {
    font-size: 28px;
    font-weight: 600;
    letter-spacing: -0.022em;
    color: var(--ink);
    margin: 0 0 4px;
}

.hero-bio[b-ess5th4qpi] {
    color: var(--ink-2);
    font-size: 14px;
    line-height: 1.5;
    max-width: 46ch;
    margin: 0;
}

.hero-bio--empty a[b-ess5th4qpi] {
    color: var(--brand);
    font-weight: 600;
    text-decoration: none;
}

.hero-bio--empty a:hover[b-ess5th4qpi] {
    text-decoration: underline;
}

/* align-items:center is load-bearing: .icon-btn carries an explicit 44px height and .btn a 48px
   one, so the default `stretch` leaves the gear top-aligned against the buttons beside it. */
.hero-actions[b-ess5th4qpi] {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    position: relative;
    z-index: 1;
}

.hero-settings svg[b-ess5th4qpi] {
    width: 20px;
    height: 20px;
}

/* .panel, .panel-title, .field-row, .field-label and .field-value now live in app.css — promoted
   when Settings became their second consumer. */
/* /Components/Pages/Settings.razor.rz.scp.css */
/* Panel, panel-title and the field-row set come from app.css (promoted from Profile when this
   page became their second consumer). Everything here is this page's own layout. */

.settings-page[b-r60upki8ee] {
    max-width: 720px;
    margin: 0 auto;
    padding: var(--s8) 1.25rem 3rem;
}

.settings-head[b-r60upki8ee] {
    display: flex;
    align-items: center;
    gap: var(--s3);
    margin-bottom: var(--s6);
}

/* 44px tap target per rule 9, sized from the icon rather than given a background — this is a
   back affordance, not a control that needs a surface. */
.settings-back[b-r60upki8ee] {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 44px;
    height: 44px;
    margin-left: -0.65rem;
    border-radius: var(--r-ctl);
    color: var(--ink);
    text-decoration: none;
    transition: background-color 0.15s ease;
}

.settings-back:hover[b-r60upki8ee] {
    background: var(--fill);
}

.settings-back svg[b-r60upki8ee] {
    width: 24px;
    height: 24px;
}

.settings-title[b-r60upki8ee] {
    margin: 0;
    font-size: 28px;
    font-weight: 600;
    letter-spacing: -0.022em;
    color: var(--ink);
}

/* Outcome of the last form post. Border-only for the error case, matching the input error
   pattern — the surface never floods with colour. */
.settings-flash[b-r60upki8ee] {
    margin: 0 0 var(--s5);
    padding: var(--s3) var(--s4);
    border-radius: var(--r-ctl);
    border: 1.5px solid transparent;
    font-size: 14px;
}

.settings-flash--ok[b-r60upki8ee] {
    background: var(--fill);
    color: var(--ink);
}

.settings-flash--error[b-r60upki8ee] {
    border-color: var(--danger);
    color: var(--danger);
}

/* A label/hint block on the left, the control on the right. Wraps below 560px so a long hint
   doesn't squeeze the control down to nothing. */
.setting-row[b-r60upki8ee] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s5);
    flex-wrap: wrap;
}

.setting-row + .setting-row[b-r60upki8ee] {
    margin-top: var(--s5);
    padding-top: var(--s5);
    border-top: 1px solid var(--line);
}

.setting-copy[b-r60upki8ee] {
    display: flex;
    flex-direction: column;
    gap: var(--s1);
    min-width: 0;
    flex: 1 1 16rem;
}

.setting-label[b-r60upki8ee] {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* --ink-2 rather than --ink-3: these hints explain what a control does, which is exactly the
   "has to be read to act on" line the contrast note in crystalTi.md draws. */
.setting-hint[b-r60upki8ee] {
    font-size: 13px;
    line-height: 1.5;
    color: var(--ink-2);
    max-width: 46ch;
}

.setting-form[b-r60upki8ee] {
    display: flex;
    flex-direction: column;
    gap: var(--s1);
    padding-bottom: var(--s5);
    margin-bottom: var(--s2);
    border-bottom: 1px solid var(--line);
}

.setting-form .setting-hint[b-r60upki8ee] {
    margin-bottom: var(--s2);
}

.setting-form__controls[b-r60upki8ee] {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
}

/* The .field recipe. app.css scopes .input under .auth-card, so this page defines its own —
   promote the pair if a third form-bearing page turns up. */
.setting-form__controls .input[b-r60upki8ee] {
    flex: 1 1 16rem;
    min-width: 0;
    height: 48px;
    padding: 0 var(--s3);
    background: var(--fill);
    color: var(--ink);
    border: 1.5px solid transparent;
    border-radius: var(--r-ctl);
    font-family: inherit;
    font-size: 15px;
}

.setting-form__controls .input:focus[b-r60upki8ee] {
    background: var(--surface);
    border-color: var(--ink);
    outline: none;
}

/* The bio field's height:48px would otherwise come from .input above — a 3-row textarea needs
   its own box height and internal padding instead of the single-line input's centred text. */
.setting-form__controls textarea.input[b-r60upki8ee] {
    height: auto;
    min-height: 88px;
    padding: var(--s3);
    font-family: inherit;
    resize: vertical;
}

/* File inputs render their own button chrome, which .input's padding/border recipe doesn't fit —
   this only needs to line up with the avatar preview and the Upload button beside it. */
.setting-form__controls input[type="file"].input[b-r60upki8ee] {
    height: auto;
    background: none;
    border: none;
    padding: 0;
    flex: 1 1 14rem;
}

.setting-form__controls .btn[b-r60upki8ee] {
    flex: none;
}

/* The form posts, so its button is the page's one primary action; the sign-out below is ghost. */
.setting-row form[b-r60upki8ee] {
    margin: 0;
    flex: none;
}
