/* GitHub Skills — Latest Activity feed (homepage, directly below hero).
   A "terminal card" treatment — echoes the hero's own $ prompt / Ctrl K motif —
   instead of a generic card grid. Reuses global tokens only; language dots use
   the public, stable GitHub linguist palette (a recognized dev-tool convention,
   not a new brand hue), kept small so they read as data, not decoration. */

.gsf-section {
    padding: var(--space-12) 0;
}

.gsf-loadmore {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: none;
    border-top: 1px solid var(--border-color);
    background: var(--bg-secondary);
    color: var(--text-secondary);
    font-size: var(--text-sm);
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

.gsf-loadmore:hover:not(:disabled),
.gsf-loadmore:focus-visible:not(:disabled) {
    color: var(--accent-color);
}

.gsf-loadmore:disabled {
    cursor: default;
    opacity: .65;
}

.gsf-loadmore[hidden] {
    display: none;
}

.gsf-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
}

.gsf-head h2 {
    font-size: var(--text-2xl);
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-primary);
    letter-spacing: -0.01em;
}

.gsf-live {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success-color);
    display: inline-block;
    box-shadow: 0 0 0 0 var(--success-color);
    animation: gsfPulse 2.4s ease-out 3;
}

@keyframes gsfPulse {
    0%   { box-shadow: 0 0 0 0 rgba(5, 150, 105, .45); }
    100% { box-shadow: 0 0 0 8px rgba(5, 150, 105, 0); }
}

.gsf-head-right {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
}

.gsf-tracked {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
}

.gsf-viewall {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--accent-color);
    text-decoration: none;
    white-space: nowrap;
}

.gsf-viewall:hover,
.gsf-viewall:focus-visible {
    text-decoration: underline;
}

/* ---- live counters strip (real DB/catalog counts only — never invented) ---- */

.gsf-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1px;
    background: var(--border-color);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    overflow: hidden;
    margin-bottom: var(--space-6);
}

.gsf-stat-tile {
    background: var(--bg-primary);
    padding: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.gsf-stat-num {
    font-size: var(--text-2xl);
    font-weight: 800;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

.gsf-stat-label {
    font-size: var(--text-xs);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: .03em;
}

/* ---- 2/3 skills + 1/3 live activity ---- */

.gsf-main-grid {
    display: grid;
    /* minmax(0, Nfr), not plain Nfr: a grid track's default min-width is
       `auto`, so an unbreakable child (the monospace --tab=rising path) would
       force the track wider and overflow the viewport on mobile. */
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    /* No gap: one card, not two side by side. The chrome (border/radius/
       shadow/background) that used to live on each .gsf-term now lives here,
       and the right column gets a single divider line instead — same visual
       weight as a tab divider inside one panel. */
    align-items: stretch;
    border-radius: var(--border-radius-lg);
    border: 1px solid var(--border-color);
    background: var(--bg-primary);
    box-shadow: var(--shadow-md);
    overflow: hidden;
}

.gsf-skills-col,
.gsf-activity-col {
    display: flex;
}

.gsf-activity-col {
    /* A soft seam, not a hard ruled line: a 1px border read as two boxes
       stitched together rather than one panel. A faint shadow has the same
       job (marking where one half ends) without the stark edge. */
    box-shadow: -1px 0 0 0 var(--border-color), -8px 0 10px -9px rgba(0, 0, 0, .12) inset;
}

.gsf-skills-col .gsf-term,
.gsf-activity-col .gsf-term {
    display: flex;
    flex-direction: column;
    width: 100%;
    /* A shared fixed height, not "however tall the content happens to be":
       the skills panel (fixed page size + pager) and the activity stream (as
       many real events as exist) naturally land at different heights. The
       feed area below flexes to fill it and scrolls internally if its own
       content doesn't fill or overflows it — so the two halves stay level. */
    height: 600px;
    border: none;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
}

.gsf-feed,
.gsf-act-feed {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    /* Reserve the scrollbar's own track instead of letting it float over the
       last few pixels of row content (it was overlapping the activity feed's
       time column). Falls back to nothing on browsers without support —
       there's still padding below to keep text clear of the old overlap. */
    scrollbar-gutter: stable;
}

.gsf-row,
.gsf-act-row {
    padding-right: var(--space-4);
}

@media (max-width: 980px) {
    .gsf-main-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .gsf-activity-col {
        box-shadow: 0 -1px 0 0 var(--border-color), 0 -8px 10px -9px rgba(0, 0, 0, .12) inset;
    }
}

.gsf-col-label {
    margin: 0;
    padding: var(--space-3) var(--space-4) var(--space-2);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--text-secondary);
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* ---- skills tablist ---- */

.gsf-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: var(--space-2) var(--space-2) 0;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
}

.gsf-tab {
    position: relative;
    flex: 1;
    min-width: 108px;
    /* Taller than the old padding gave it: a bigger, obviously-pressable
       target reads as clickable before anyone even hovers it. */
    padding: 13px var(--space-3);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-secondary);
    background: transparent;
    border: none;
    border-radius: var(--border-radius-sm) var(--border-radius-sm) 0 0;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
    transition: color var(--transition-speed) var(--transition-curve),
                background var(--transition-speed) var(--transition-curve);
}

/* An underline that only exists on the selected tab (not a static rule under
   all of them) + a background tint make the affordance obvious without
   waiting for a hover: this is a button, not a label. */
.gsf-tab::after {
    content: "";
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 0;
    height: 2px;
    border-radius: 2px 2px 0 0;
    background: var(--accent-color);
    opacity: 0;
    transform: scaleX(.6);
    transition: opacity var(--transition-speed) var(--transition-curve),
                transform var(--transition-speed) var(--transition-curve);
}

.gsf-tab[aria-selected="true"] {
    color: var(--accent-color);
    background: var(--bg-primary);
}

.gsf-tab[aria-selected="true"]::after {
    opacity: 1;
    transform: scaleX(1);
}

.gsf-tab:hover:not([aria-selected="true"]) {
    color: var(--text-primary);
    background: var(--bg-primary);
}

.gsf-tab:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: -2px;
}

/* ---- terminal card chrome (the card itself is .gsf-main-grid now — see
   above — so .gsf-term is just the inner flex column, no border of its own) ---- */

.gsf-term {
    overflow: hidden;
}

.gsf-term-bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
}

.gsf-term-dots {
    display: inline-flex;
    gap: 6px;
    flex: none;
}

.gsf-term-dots i {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    display: block;
}

.gsf-term-dots i:nth-child(1) { background: var(--error-color); opacity: .55; }
.gsf-term-dots i:nth-child(2) { background: var(--warning-color); opacity: .55; }
.gsf-term-dots i:nth-child(3) { background: var(--success-color); opacity: .55; }

.gsf-term-path {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gsf-term-flag {
    /* text-secondary, not text-muted: #94a3b8 on white measures 2.56:1, below AA for real text */
    color: var(--text-secondary);
}

.gsf-term-count {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
    flex: none;
}

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

.gsf-feed {
    display: flex;
    flex-direction: column;
    font-variant-numeric: tabular-nums;
}

.gsf-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--border-color);
    text-decoration: none;
    color: inherit;
    position: relative;
    animation: gsfRowIn .34s var(--transition-curve) backwards;
    transition: background var(--transition-speed) var(--transition-curve);
}

.gsf-row:last-child {
    border-bottom: none;
}

.gsf-row:nth-child(1) { animation-delay: .02s; }
.gsf-row:nth-child(2) { animation-delay: .08s; }
.gsf-row:nth-child(3) { animation-delay: .14s; }
.gsf-row:nth-child(4) { animation-delay: .20s; }
.gsf-row:nth-child(5) { animation-delay: .26s; }
.gsf-row:nth-child(6) { animation-delay: .32s; }

@keyframes gsfRowIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.gsf-row::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--gsf-lang, transparent);
    opacity: 0;
    transition: opacity var(--transition-speed) var(--transition-curve);
}

.gsf-row:hover::before,
.gsf-row:focus-visible::before {
    opacity: .9;
}

.gsf-row.is-new::before {
    opacity: 1;
    background: var(--success-color);
}

.gsf-row:hover,
.gsf-row:focus-visible {
    background: var(--bg-secondary);
}

.gsf-row:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: -2px;
}

.gsf-row .bsk-avatar {
    width: 28px;
    height: 28px;
    border-radius: var(--border-radius-sm);
    flex: none;
    object-fit: cover;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    transition: box-shadow var(--transition-speed) var(--transition-curve);
}

.gsf-row:hover .bsk-avatar,
.gsf-row:focus-visible .bsk-avatar {
    box-shadow: 0 0 0 2px var(--bg-secondary), 0 0 0 3px var(--gsf-lang, var(--accent-color));
}

.gsf-main {
    min-width: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.gsf-title-line {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: nowrap;
    min-width: 0;
}

.gsf-title {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.gsf-owner {
    color: var(--text-secondary);
    font-weight: 500;
}

.gsf-row:hover .gsf-title,
.gsf-row:focus-visible .gsf-title {
    color: var(--accent-color);
}

/* Icon-only now (was icon+text label) — the full word shows as a native
   tooltip on hover/focus via the `title` attribute, not inline text, so a
   row stays one compact line instead of wrapping under a wordy pill. */
.gsf-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    font-size: 9.5px;
    border-radius: 50%;
    flex: none;
    cursor: default;
}

/* Solid pills, not tinted text: measured — accent-orange text on its own 14%
   tint is 3.0:1 on light backgrounds, below AA for 10.5px bold. White on a
   darker luminance variant of the SAME orange hue (#c2410c, still orange, not
   a new brand color) measures 5.18:1. Dark theme flips light-text-on-dark to
   dark-text-on-light since accent-*-dark tokens are already light enough. */
.gsf-chip-trend {
    color: #ffffff;
    background: #c2410c;
}

.gsf-chip-multi {
    color: #ffffff;
    background: var(--accent-purple);
}

/* Measured: white on light-theme accent (#0066cc) is 5.57:1 (OK); on
   dark-theme accent (#4d9fe6) it drops to 2.83:1 — same dark-ink flip as the
   pager's active page number uses. */
.gsf-chip-member {
    color: #ffffff;
    background: var(--accent-color);
}

[data-theme="dark"] .gsf-chip-trend {
    color: #0f172a;
    background: var(--accent-orange);
}

[data-theme="dark"] .gsf-chip-multi {
    color: #0f172a;
    background: var(--accent-purple);
}

[data-theme="dark"] .gsf-chip-member {
    color: #0f172a;
}

.gsf-subline {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 11px;
    color: var(--text-secondary);
    flex-wrap: wrap;
    row-gap: 1px;
    min-width: 0;
}

.gsf-subline .gsf-updated {
    margin-left: auto;
}

.gsf-lang {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.gsf-lang-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--gsf-lang, var(--text-muted));
    display: inline-block;
}

.gsf-plats {
    display: flex;
    gap: 5px;
}

.gsf-plat {
    display: flex;
}

.gsf-plat .bsk-logo {
    width: 14px;
    height: 14px;
    display: block;
    color: var(--text-muted);
}

.gsf-stat {
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    min-width: 52px;
}

.gsf-stars {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-primary);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.gsf-stars i {
    color: var(--warning-color);
    font-size: .8em;
}

.gsf-gain {
    font-size: 10.5px;
    font-weight: 600;
    color: var(--success-color);
}

.gsf-bar {
    width: 42px;
    height: 3px;
    border-radius: 999px;
    background: var(--bg-tertiary);
    display: block;
    overflow: hidden;
}

.gsf-bar-fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--gsf-lang, var(--accent-color));
    width: calc(var(--gsf-step, 0) * 5%);
    transition: width .5s var(--transition-curve);
}

.gsf-updated {
    flex: none;
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
}

/* ---- live activity (1/3 column) + its view switcher ---- */

.gsf-view-head {
    position: relative;
    border-bottom: 1px solid var(--border-color);
}

.gsf-view-trigger {
    width: 100%;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--text-secondary);
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: inherit;
    text-align: left;
}

.gsf-view-trigger:hover,
.gsf-view-trigger:focus-visible,
.gsf-view-trigger[aria-expanded="true"] {
    color: var(--text-primary);
}

.gsf-view-trigger i {
    margin-left: auto;
    font-size: 10px;
    transition: transform var(--transition-speed) var(--transition-curve);
}

.gsf-view-trigger[aria-expanded="true"] i {
    transform: rotate(180deg);
}

/* Opens upward ("dropup"): anchored to the trigger's bottom edge, growing up
   over the row list rather than pushing content down or spilling past the
   card's own bottom edge. */
/* position: fixed, not absolute — the card above it clips with overflow:
   hidden (for its own rounded corners), and an absolutely-positioned dropup
   gets clipped by that the moment it tries to open above the trigger. Fixed
   positioning's containing block is the viewport, so JS sets left/bottom/
   width from the trigger's real on-screen rect and the menu always clears
   every ancestor's clipping. */
.gsf-view-menu {
    position: fixed;
    background: var(--bg-primary);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-lg);
    padding: 4px;
    list-style: none;
    z-index: 50;
}

.gsf-view-menu[hidden] {
    display: none;
}

.gsf-view-opt {
    width: 100%;
    display: block;
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-primary);
    background: transparent;
    border: none;
    border-radius: var(--border-radius-sm);
    text-align: left;
    cursor: pointer;
    font-family: inherit;
}

.gsf-view-opt:hover,
.gsf-view-opt:focus-visible {
    background: var(--bg-secondary);
}

.gsf-view-opt[aria-checked="true"] {
    color: var(--accent-color);
    font-weight: 700;
}

.gsf-view-panel[hidden] {
    display: none;
}

.gsf-view-empty {
    margin: 0;
    padding: var(--space-6) var(--space-4);
    text-align: center;
    font-size: var(--text-sm);
    color: var(--text-secondary);
}

.gsf-live-sm {
    width: 6px;
    height: 6px;
    animation: none; /* the column label isn't the page's one live indicator — no duplicate pulse */
}

.gsf-act-feed {
    display: flex;
    flex-direction: column;
    font-variant-numeric: tabular-nums;
}

.gsf-act-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-color);
    animation: gsfActIn .4s var(--transition-curve) backwards;
    text-decoration: none;
    color: inherit;
}

a.gsf-act-row:hover,
a.gsf-act-row:focus-visible {
    background: var(--bg-secondary);
}

.gsf-act-row:last-child {
    border-bottom: none;
}

@keyframes gsfActIn {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: translateY(0); }
}

.gsf-act-ic {
    width: 30px;
    height: 30px;
    border-radius: var(--border-radius-sm);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--accent-color);
    font-size: var(--text-xs);
    flex: none;
}

.gsf-act-main {
    min-width: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.gsf-act-tool {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gsf-act-verb {
    font-weight: 400;
    color: var(--text-secondary);
}

.gsf-act-loc {
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Real SVG flags (flag-icons CDN), not Unicode flag emoji — regional-
   indicator emoji silently fail to compose into a flag on several real
   platforms (Windows without an updated emoji font shows two letters or
   nothing), so an image-based flag is the only cross-platform-reliable one. */
.gsf-flag {
    display: inline-block;
    vertical-align: -1px;
    width: 14px;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .08);
    margin-right: 5px;
}

.gsf-act-time {
    flex: none;
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
}

@media (max-width: 640px) {
    .gsf-term-count,
    .gsf-tracked {
        display: none;
    }

    .gsf-bar {
        width: 44px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .gsf-live,
    .gsf-row,
    .gsf-act-row {
        animation: none;
    }

    .gsf-bar-fill {
        transition: none;
    }
}
