/* ============================================================================
   v0.8.0 - the friends page (/friends), issue #4.

   Mobile first, because the owner directive makes the 375px viewport
   verification priority number 1: the base rules here ARE the phone layout and
   the media queries only widen it. Every colour resolves through the tokens in
   00-tokens-base.css so the dark theme (24-theme-dark.css, loaded last) needs
   no per-rule override here.

   The shared-task bar segment colours are NOT defined in this file. They come
   from AssigneePalette in Chronos.Domain and arrive as an inline background on
   each segment, so the bar a test asserts and the bar a user sees are drawn
   from one list. The --seg-* variables below only mirror that ring for the
   /studio specimens and are covered by a parity test.
   ============================================================================ */

:root {
    --seg-0: #6C8CFF;
    --seg-1: #F5A524;
    --seg-2: #2FBF71;
    --seg-3: #E5484D;
    --seg-4: #A855F7;
    --seg-5: #22C1D6;
    --seg-6: #EC4899;
    --seg-7: #94A3B8;
}

/* ---------- topbar entry point ----------
   v0.8.3.0: the board's Friends entry became a section of the segmented strip, so
   .friends-topbar-link and .friends-topbar-dot moved out of this file entirely - the badge
   now rides the counter-skewed segment body as .topnav-dot (31-topnav.css). Nothing about
   the board's top bar is styled from here any more; what follows is the /friends page.   */

.friends-page {
    max-width: 1080px;
    margin: 0 auto;
    padding: 16px 12px 48px;
}

/* ---------- pyramid layout (owner redesign directive, v0.9.8.1) ----------
   A stretched, full-width card on a wide monitor reads as clutter, so every card in the pyramid
   carries its own max-width (420-520px) and the group is centred - the free space either side IS
   the margin, not something to fill. Plain flex-wrap, no fixed positioning.

   The hero owns its row via a ::after line-break element, NOT via flex-basis:100%. The obvious
   flex-basis approach silently fails here: flex line packing uses the item's hypothetical size
   AFTER max-width clamps it, so a 520px-capped hero leaves the rest of a wide row free and the
   next card climbs up beside it - measured live as an inverted pyramid (2 on top, 1 below) at
   1280px. The zero-height 100%-wide ::after occupies the remainder of the hero's row instead,
   so nothing can share it at any container width, while the bottom pair still wraps into a
   column once the container is too narrow for them to sit side by side. */
.friends-pyramid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-start;
    gap: 20px;
}

/* The row break after the hero. Height zero so the pyramid's own gap stays the only vertical
   rhythm; basis 100% so no later flex item fits on the hero's line. */
.friends-pyramid::after {
    content: "";
    order: 1;
    flex-basis: 100%;
    height: 0;
}

/* Compound selectors (.friends-card.friends-pyramid-*) so this beats the plain .friends-card
   margin-bottom declared further down the file regardless of source order - relying on cascade
   order here would be a trap for the next edit. */
.friends-card.friends-pyramid-hero,
.friends-card.friends-pyramid-card {
    margin-bottom: 0;   /* the pyramid's own gap replaces .friends-card's stacked margin */
    min-width: 0;
}

.friends-pyramid-hero {
    order: 0;
    flex: 0 1 520px;
    max-width: 520px;
}

.friends-pyramid-card {
    order: 2;
    flex: 0 1 440px;
    max-width: 480px;
}

/* Sub-blocks folded into the friends hub card (add form, incoming/outgoing requests, the friend
   list, shared tasks) used to each be their own top-level card; they keep their own heading but
   share one card body now, separated by a rule instead of a card boundary. */
.friends-subsection + .friends-subsection {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--chronos-outline);
}

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

.friends-header {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.friends-back {
    color: var(--chronos-fg-muted);
    text-decoration: none;
    font-size: 13px;
    flex: 0 0 auto;
}

.friends-back:hover { color: var(--chronos-violet); }

.friends-title {
    font-family: var(--chronos-font-display);
    font-size: 20px;
    font-weight: 700;
    margin: 0;
    flex: 1 1 auto;
}

/* Blazor's enhanced navigation stamps tabindex="-1" on the page's first heading and focuses it
   after a swap so a screen reader announces the new page. The app's global focus ring then draws
   a violet box around the title on every single arrival, which reads as a rendering bug.
   Suppressed unconditionally, NOT via :not(:focus-visible): Chrome reports focus-visible as true
   for this programmatic focus, so the guarded form never matches (verified in the browser). This
   is safe because a tabindex="-1" element cannot be reached by tabbing - no keyboard user can
   deliberately land here, so the ring conveys nothing. The heading still gets announced. */
.friends-title:focus { outline: none; }

/* The slot counter doubles as the cap surface: it turns warm the moment the
   tier limit is reached, which is the same moment the add form disappears. */
.friends-slots {
    flex: 0 0 auto;
    font-family: var(--chronos-font-mono);
    font-size: 13px;
    padding: 3px 10px;
    border-radius: var(--radius-pill);
    background: var(--chronos-chip-bg);
    color: var(--chronos-fg-secondary);
}

.friends-slots.is-full {
    background: color-mix(in srgb, var(--chronos-red) 14%, transparent);
    color: var(--chronos-red);
}

/* ---------- cards ---------- */

.friends-card { margin-bottom: 12px; padding: 14px; }

.friends-h2 {
    font-size: 14px;
    font-weight: 700;
    margin: 0 0 10px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.friends-empty {
    color: var(--chronos-fg-muted);
    font-size: 13px;
    margin: 4px 0;
}

.friends-msg {
    font-size: 13px;
    padding: 9px 12px;
    border-radius: var(--radius-card);
    margin: 0 0 12px;
}

.friends-msg.is-ok {
    background: color-mix(in srgb, #2FBF71 14%, transparent);
    color: #1B7F4C;
}

.friends-msg.is-err {
    background: color-mix(in srgb, var(--chronos-red) 12%, transparent);
    color: var(--chronos-red);
}

.friends-count-dot {
    background: var(--chronos-red);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--radius-pill);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ---------- add form ---------- */

.friends-add-form { display: flex; gap: 8px; flex-wrap: wrap; }

.friends-input {
    flex: 1 1 160px;
    min-width: 0;
    padding: 9px 12px;
    border: 1px solid var(--chronos-outline);
    border-radius: var(--radius-card);
    font-family: var(--chronos-font-sans);
    font-size: 14px;
    background: var(--chronos-card-bg);
    color: var(--chronos-fg-primary);
}

.friends-input:focus {
    outline: 2px solid var(--chronos-violet);
    outline-offset: 1px;
}

.friends-cap-note { font-size: 13px; color: var(--chronos-fg-secondary); margin: 0; }

.friends-upgrade { color: var(--chronos-violet); font-weight: 600; margin-left: 6px; }

/* ---------- rows ---------- */

.friends-list, .shared-list, .board-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.friend-row, .board-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 0;
    border-top: 1px solid var(--chronos-outline);
}

.friends-list > .friend-row:first-child,
.board-list > .board-row:first-child { border-top: none; }

.friend-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
    background: var(--chronos-chip-bg);
}

.friend-avatar-initial {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 14px;
    color: var(--chronos-fg-secondary);
}

.friend-name, .board-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--chronos-fg-primary);
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
}

.friend-name:hover, .board-name:hover { color: var(--chronos-violet); }

.friend-pending { font-size: 12px; color: var(--chronos-fg-muted); }

.friend-actions { display: flex; gap: 6px; flex: 0 0 auto; }

.friend-actions form { margin: 0; }

.btn-sm { font-size: 12px; padding: 5px 10px; }

.friend-remove:hover { color: var(--chronos-red); }

/* ---------- referral (issue #referral) ----------
   Reuses .friends-list / .friend-row / .friends-msg wholesale - only what is genuinely new to
   this block (the link row, the counter, the status pill) gets its own rule below. */

.referral-intro {
    font-size: 13px;
    color: var(--chronos-fg-secondary);
    margin: 0 0 10px;
}

.referral-link-row {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.referral-link-input {
    flex: 1 1 160px;
    min-width: 0;
    font-family: var(--chronos-font-mono);
    font-size: 12px;
    color: var(--chronos-fg-secondary);
}

/* v0.9.8.1: the copy button became an icon button (Material Icons content_copy) - the visible
   "Copy" text moved to aria-label, same behaviour and the same data-track the telemetry hook
   reads. Square, not pill, so it reads as a distinct action next to the read-only link field
   rather than as another pill in the row. */
.referral-copy-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: 1px solid var(--chronos-outline);
    border-radius: var(--radius-card);
    background: var(--chronos-violet);
    color: #fff;
    transition: background .15s, transform .12s;
}

.referral-copy-btn:hover { transform: translateY(-1px); }

.referral-copy-btn .material-icons { font-size: 19px; }

.referral-copy-toast { margin: 8px 0 0; }

/* Two slots, not a "0 / 2" string - each one is empty / in flight (a pending row) / confirmed.
   Reuses the same three colours as .pair-streak and .referral-status below it, so "in flight"
   reads as the same amber everywhere on the page and "confirmed" the same green. */
.referral-slots {
    display: flex;
    gap: 6px;
    margin: 12px 0 4px;
}

.referral-slot {
    flex: 1 1 0;
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--chronos-chip-bg);
}

.referral-slot.is-pending {
    background: color-mix(in srgb, #F5A524 55%, var(--chronos-chip-bg));
}

.referral-slot.is-confirmed { background: #2FBF71; }

.referral-counter {
    font-family: var(--chronos-font-mono);
    font-size: 13px;
    font-weight: 700;
    margin: 0 0 6px;
    color: var(--chronos-fg-primary);
}

.referral-list { margin-top: 4px; }

.referral-row { justify-content: space-between; }

.referral-name {
    flex: 0 1 auto;
    min-width: 0;
    font-weight: 600;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The friend's own streak toward the day-7 confirm gate - reuses .bar-row/.bar/.bar-fill/.bar-pct
   from 06-planning-tasks.css wholesale (see the shared-task bar below); only the sizing needed to
   grow into the row's remaining space is new here. */
.referral-progress-row {
    flex: 1 1 auto;
    min-width: 100px;
}

.referral-status {
    flex: 0 0 auto;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
}

.referral-status.is-pending {
    background: var(--chronos-chip-bg);
    color: var(--chronos-fg-muted);
}

.referral-status.is-confirmed {
    background: color-mix(in srgb, #2FBF71 18%, transparent);
    color: #1B7F4C;
}

.referral-rules {
    font-size: 11px;
    margin: 10px 0 0;
}

/* ---------- pair streak (Duolingo-style) ---------- */

.pair-streak {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    font-family: var(--chronos-font-mono);
    font-size: 12px;
    font-weight: 700;
    flex: 0 0 auto;
}

.pair-streak.is-live {
    background: color-mix(in srgb, #F5A524 18%, transparent);
    color: #A6600A;
}

.pair-streak.is-cold {
    background: var(--chronos-chip-bg);
    color: var(--chronos-fg-muted);
}

.pair-streak-flame::before { content: "\1F525"; font-size: 11px; }

.pair-streak.is-cold .pair-streak-flame::before {
    content: "\2744";
    opacity: .55;
}

/* The unit ("d"), so the badge reads as a duration instead of a bare digit. This row
   used to print the pair streak AND the friend's personal streak as two unlabelled
   numbers side by side, which was impossible to tell apart; the personal one now
   lives only in the rating, where a whole column means the same thing. */
.pair-streak-label {
    font-size: 10px;
    font-weight: 600;
    opacity: .75;
}

/* ---------- shared tasks ----------

   Almost nothing here: a shared task reuses the board's own task card wholesale
   (.task-row / .task-head / .task-body / .task-text / .task-title from
   06-planning-tasks.css, and .bar-row / .bar / .bar-fill / .bar-pct from
   03-filter-ribbon.css). Only the parts that are genuinely new to this feature -
   the split fill and the participant legend - are styled below. If you find
   yourself re-declaring a task-card rule here, reuse it instead. */

.shared-list { display: flex; flex-direction: column; gap: 10px; }

/* The one real difference from an ordinary task bar: the track holds one fill per
   participant instead of a single one. The leftover space at the right is the part
   of the task nobody has done yet, so total progress and per-person effort read at
   once. The track's own overflow:hidden rounds the outer ends, so the segments butt
   together square and do not each look like a separate pill. */
.bar.is-segmented { display: flex; }
.bar.is-segmented .bar-fill { border-radius: 0; }

.shared-legend {
    list-style: none;
    margin: 7px 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
}

.shared-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    color: var(--chronos-fg-secondary);
}

.shared-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    display: inline-block;
    flex: 0 0 auto;
}

.shared-legend-pct { font-family: var(--chronos-font-mono); color: var(--chronos-fg-muted); }

/* Your own row in the legend, so you can find your colour without counting. */
.shared-legend-item.is-me .shared-legend-name { font-weight: 700; color: var(--chronos-fg-primary); }

.shared-progress-form {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
}

.shared-range { flex: 1 1 auto; min-width: 0; accent-color: var(--chronos-violet); }

/* ---------- global streak rating ---------- */

.friends-myrank {
    font-size: 13px;
    color: var(--chronos-fg-secondary);
    margin: 0 0 10px;
    padding: 8px 12px;
    border-radius: var(--radius-card);
    background: var(--chronos-card-inset);
}

.board-rank {
    font-family: var(--chronos-font-mono);
    font-size: 12px;
    color: var(--chronos-fg-muted);
    min-width: 28px;
    flex: 0 0 auto;
    text-align: center;
}

.board-medal { font-size: 17px; line-height: 1; }

/* v0.9.8.1: the plain "flame + number" became a horizontal bar - length relative to the longest
   streak on the visible page (BoardBarPercent in Friends.razor.cs), value still spelled out right
   next to it. Reuses the same violet track/fill tokens as .bar/.bar-fill (03-filter-ribbon.css)
   rather than inventing a second bar look on the same page. */
.board-bar-wrap {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: 84px;
    flex: 0 0 auto;
}

.board-bar-track {
    flex: 1 1 auto;
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--chronos-violet-light);
    overflow: hidden;
}

.board-bar-fill {
    display: block;
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--chronos-violet);
    transition: width 0.25s ease-out;
}

.board-bar-value {
    flex: 0 0 auto;
    min-width: 16px;
    text-align: right;
    font-family: var(--chronos-font-mono);
    font-size: 12px;
    font-weight: 700;
    color: var(--chronos-fg-secondary);
}

/* The podium. Each of the three carries its own tint on the row and a matching left
   edge, so the top of the board reads as a ranking at a glance rather than as the
   first three lines of a list. Colours are flat, not gradients, so they survive the
   dark theme without a second set of overrides. */
.board-row.is-gold,
.board-row.is-silver,
.board-row.is-bronze {
    border-radius: var(--radius-card);
    padding-left: 8px;
    padding-right: 8px;
    border-top: none;
    border-left: 3px solid transparent;
}

.board-row.is-gold {
    background: color-mix(in srgb, #F5A524 14%, transparent);
    border-left-color: #F5A524;
}

.board-row.is-silver {
    background: color-mix(in srgb, #A9B4C2 16%, transparent);
    border-left-color: #A9B4C2;
}

.board-row.is-bronze {
    background: color-mix(in srgb, #C77B3A 14%, transparent);
    border-left-color: #C77B3A;
}

.board-row.is-gold .board-bar-value { color: #A6600A; }
.board-row.is-gold .board-bar-fill { background: #F5A524; }

/* Your own row wins over a medal tint - finding yourself is the whole point of the
   "you are #N of M" line above, so it must be findable in the list too. */
.board-row.is-self {
    background: color-mix(in srgb, var(--chronos-violet) 12%, transparent);
    border-radius: var(--radius-card);
    padding-left: 8px;
    padding-right: 8px;
    border-top: none;
    border-left: 3px solid var(--chronos-violet);
}

.board-row.is-self .board-name { color: var(--chronos-violet); font-weight: 700; }

/* A word, not a bare dot. The dot said "this person is somehow special" and left the
   reader to guess which way. */
.board-friend-chip {
    flex: 0 0 auto;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--chronos-violet) 16%, transparent);
    color: var(--chronos-violet);
}

/* The board is the one place a tier badge is genuinely informative (it explains why
   someone can hold 10 friends), but it must not out-shout the streak number. */
.board-list .tier-badge {
    flex: 0 0 auto;
    transform: scale(.85);
    transform-origin: right center;
}

/* ---------- wider screens ---------- */

@media (min-width: 721px) {
    .friends-page { padding: 24px 16px 64px; }
    .friends-title { font-size: 24px; }
    .friends-card { padding: 18px; }
}

/* The 375px phone is the primary target; below 480 the friend row's actions are the
   first thing to run out of room, so let them wrap under the name instead of
   squeezing the username to an unreadable stub. */
@media (max-width: 480px) {
    .friend-row { flex-wrap: wrap; }
    .friend-actions { margin-left: auto; }
    .friend-name { flex: 1 1 40%; }

    /* The BOARD must NOT wrap: a leaderboard is read as a column of ranks, and a row
       that spills onto a second line breaks the vertical rhythm that makes it
       scannable. Instead the tier badge - the least load-bearing item on the row -
       drops out, which is enough to fit rank, avatar, name, friend chip and the
       streak on one line at 375px. The badge is back from 481px up. */
    .board-list .tier-badge { display: none; }
    .board-name { min-width: 0; }
    .board-bar-wrap { width: 60px; }
}

@media (prefers-reduced-motion: reduce) {
    .shared-bar-seg { transition: none; }
}

/* ============================================================================
   v0.8.1 - controls moved OUT of the bottom compose bar and INTO the create
   modal, plus the friend pickers that make a task shared.

   The three creation methods (voice / AI token / manual) used to sit along the
   bottom bar competing with the AI prompt. Side by side inside the modal they
   read as what they always were: three ways to fill the same form. Their
   original looks live in 13-compose-bar.css and are deliberately NOT reused -
   a pill sized for a toolbar is the wrong shape for a modal row.
   ============================================================================ */

.create-method-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.create-method {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 13px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--chronos-outline);
    background: var(--chronos-card-bg);
    color: var(--chronos-fg-primary);
    font-family: var(--chronos-font-sans);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .04em;
    cursor: pointer;
    white-space: nowrap;
}

.create-method .material-icons { font-size: 17px; }

.create-method:disabled { opacity: .5; cursor: default; }

/* The token button keeps its FOMO pulse - it is the one paid action in the row
   and the monetization note is explicit that this pulse is a product feature. */
.create-method.has-tokens {
    background: var(--chronos-violet);
    border-color: var(--chronos-violet);
    color: #fff;
    animation: upgrade-pulse 2.4s ease-in-out infinite;
}

.create-method-count {
    background: rgba(0, 0, 0, .28);
    border-radius: var(--radius-pill);
    padding: 1px 7px;
    font-size: 11px;
    font-weight: 700;
}

.create-method.is-recording {
    border-color: var(--chronos-red);
    color: var(--chronos-red);
}

/* v0.9.6: .is-active means SELECTED. The row is a three-way switch now, so exactly one tile
   carries this at any moment and it has to be legible at a glance - a ring outside the border
   rather than a background swap, because .has-tokens already owns the AI tile's background and
   the two would fight. outline sits outside the box, so nothing reflows when the ring appears:
   the row must not twitch as the user tries the three options. */
.create-method.is-active {
    outline: 2px solid var(--chronos-violet);
    outline-offset: 2px;
    border-color: var(--chronos-violet);
}

/* The two unfilled tiles still need a visible "on" state; the AI tile is already violet. */
.create-method.is-active:not(.has-tokens) {
    background: color-mix(in srgb, var(--chronos-violet) 14%, var(--chronos-card-bg));
    color: var(--chronos-violet);
}

.create-method:hover:not(:disabled):not(.is-active) { border-color: var(--chronos-violet); }

/* ---------- create modal: the picker body ---------- */

/* The one big box both AI routes write into. A textarea, not the bar's single-line input: this
   is the place you paste three sentences, and a field that scrolls sideways to hide what you
   just typed invites sending half a thought. It fills the prompt section's flex height, so
   resize is off - a drag handle would fight the fixed-card layout it now lives in. */
.create-prompt-input {
    width: 100%;
    flex: 1 1 auto;
    resize: none;
    min-height: 104px;
    line-height: 1.5;
    font-family: inherit;
}

.create-voice-note {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 8px;
    font-size: 12px;
    color: var(--chronos-fg-secondary);
}
.create-voice-note .material-icons { font-size: 18px; color: var(--chronos-violet); }
.create-voice-reopen { margin-left: auto; }

/* ---------- create modal: the settings block ----------

   The manual method's form. v0.9.6.3: it renders ONLY for manual - the AI routes show a
   one-line hint instead of a greyed-out copy, so the locked/disabled machinery is gone.
   Everything below strips the fieldset's stock chrome (border, margin, the padding-inline
   that would indent the whole form) so the grouping element is invisible. */
.create-settings {
    border: 0;
    margin: 0;
    padding: 0;
    min-width: 0;   /* fieldset defaults to min-content, which would stop the form shrinking */
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.create-settings-hint {
    margin: 0;
    font-size: 12px;
    line-height: 1.45;
}

/* ---------- friend picker (create modal + detail sidebar) ---------- */

.share-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.share-pick {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 11px 4px 4px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--chronos-outline);
    background: var(--chronos-card-bg);
    color: var(--chronos-fg-primary);
    font-family: var(--chronos-font-sans);
    font-size: 13px;
    cursor: pointer;
    max-width: 100%;
}

/* The avatar is the same component the friends page and the rating use, so a
   person looks like the same person wherever they appear. */
.share-pick .friend-avatar {
    width: 22px;
    height: 22px;
    font-size: 11px;
}

.share-pick-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.share-pick:hover:not(:disabled) { border-color: var(--chronos-violet); }

.share-pick:disabled { opacity: .55; cursor: default; }

.share-pick.selected {
    background: color-mix(in srgb, var(--chronos-violet) 14%, transparent);
    border-color: var(--chronos-violet);
    color: var(--chronos-violet);
    font-weight: 600;
}

.share-hint { font-size: 12px; margin: 6px 0 0; }

/* The detail sidebar is a narrow column, so its picker stacks instead of
   wrapping into ragged rows. */
.detail-sidebar .share-picker { flex-direction: column; align-items: stretch; }
.detail-sidebar .share-pick { justify-content: flex-start; }

/* ---------- create modal: keep the actions reachable on a phone ----------

   The card is a constant box (v0.9.6, owner rule stated in these words: a window that
   jumps is a sin - method switches must not resize or re-centre the dialog).

   v0.9.6.3: the card no longer scrolls as ONE piece. Scrolling the whole card meant the
   title scrolled away and, worse, the primary button started below the fold - reaching
   Generate required scrolling past the entire form. Now the head and the action row are
   pinned and only .create-modal-body between them scrolls. The AI and voice routes fit
   the body outright (their settings collapsed into a one-line hint), so they never
   scroll at all; manual's long form scrolls under chrome that never moves.

   dvh, with vh first as the fallback: on mobile Safari and Chrome the address
   bar makes 100vh taller than the visible area, which would put the pinned
   action row below the visible fold - exactly the bug this rule exists to fix. */
.modal-card.create-modal {
    height: min(calc(100vh - 24px), 560px);
    height: min(calc(100dvh - 24px), 560px);
    overflow: hidden;   /* the card itself never scrolls; the body region below does */
}

.create-modal-body {
    flex: 1 1 auto;
    min-height: 0;      /* let the flex item actually shrink below content height */
    display: flex;
    flex-direction: column;
    gap: 14px;          /* same rhythm as .modal-card's own gap */
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Reserve the scrollbar's width at all times. Without this the gutter appears and
       disappears as the content changes height and every line inside shifts sideways. */
    scrollbar-gutter: stable;
}

/* AI/voice: the prompt section drinks whatever height the fixed card has left, so the
   compact routes have no dead zone under the hint - the box you type into is what
   grows, which is also the invitation to write more than one line. */
.create-modal-body .create-prompt {
    flex: 1 1 auto;
    min-height: 0;
}
