/* Padelytics FIP profile — builds on the shared .glass-detail / .gd-* system
   in player.css (same look as the DPF player profile); only FIP-specific bits
   live here. The FIP Mænd list rows reuse the DPF .list-row grid verbatim — no
   overrides — so the middle pane matches the DPF Rangliste exactly. */

/* The Makker KPI carries a name, not a number — dial the big mono value down. */
.fip-kpi-makker .gd-kpi-value {
    font-size: 18px; line-height: 1.25; letter-spacing: -.01em;
    white-space: normal; word-break: break-word;
}

/* ── Hero meta row (bio facts lifted under the name) ──────────────────── */
.gd-hero-meta { list-style: none; margin: 8px 0 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: 6px 8px; }
.gd-hero-meta li { display: inline-flex; align-items: baseline; gap: 6px;
    padding: 4px 10px; border-radius: 999px;
    background: var(--bg-raised); border: 1px solid var(--card-border);
    font-size: 13px; font-weight: 600; color: var(--text); }
.gd-hero-meta .ghm-k { font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
    color: var(--text-dim); font-weight: 700; }

/* ── Turneringsresultater ─────────────────────────────────────────────── */
.fip-res-tally { margin: 0 0 14px; color: var(--text-dim); font-size: 14px; }
.fip-res-tally strong { color: var(--accent); font-weight: 800;
    font-family: var(--font-mono), monospace; font-size: 16px; }

/* Palmarès — one row per circuit */
.fip-palmares { list-style: none; margin: 0 0 20px; padding: 0;
    display: flex; flex-direction: column; gap: 8px; }
.fip-pal-row { display: flex; justify-content: space-between; align-items: center; gap: 12px;
    padding: 11px 14px; border-radius: 12px;
    background: var(--bg-raised); border: 1px solid var(--card-border); }
.fip-pal-circuit { font-weight: 700; color: var(--text); letter-spacing: -.01em; }
.fip-pal-counts { display: inline-flex; align-items: center; gap: 10px; }
.fip-pal-titles { font-family: var(--font-mono), monospace; font-weight: 800;
    font-size: 13px; color: var(--accent);
    padding: 3px 9px; border-radius: 999px;
    background: rgba(255, 181, 71, .10); border: 1px solid rgba(255, 181, 71, .22); }
.fip-pal-finals { font-size: 13px; color: var(--text-dim); font-weight: 600; }

/* Scope tag (e.g. "alle år") — small mono pill */
.fip-res-scope { font-family: var(--font-mono), monospace; font-size: 10px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .06em; color: var(--text-dim);
    margin-left: 7px; padding: 2px 8px; border-radius: 999px; vertical-align: middle;
    background: var(--bg-raised); border: 1px solid var(--card-border); }

/* ── Accordion block (Finaler / Turneringer): search + collapsible years ── */
.fip-acc { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--card-border); }
.fip-acc-bar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; }
.fip-acc-head { flex: none; margin: 0; font-size: 14px; font-weight: 800; color: var(--text);
    letter-spacing: -.01em; }
.fip-acc-search { flex: 1; min-width: 150px; font: inherit; font-size: 14px; color: var(--text);
    background: var(--bg-raised); border: 1px solid var(--card-border);
    border-radius: 10px; padding: 9px 12px; }
.fip-acc-search::placeholder { color: var(--text-dim); }
.fip-acc-search:focus { outline: none; border-color: var(--accent-border); }
.fip-acc-toggle { cursor: pointer; font: inherit; font-size: 13px; font-weight: 700;
    color: var(--text-dim); background: transparent; border: 1px solid var(--card-border);
    border-radius: 10px; padding: 9px 14px; white-space: nowrap; transition: color .15s, border-color .15s; }
.fip-acc-toggle:hover { color: var(--text); border-color: var(--accent-border); }
.fip-acc-empty { color: var(--text-dim); font-size: 13px; padding: 16px 2px; }

/* Year group (native <details>) */
.fy-group { border-top: 1px solid var(--card-border); }
.fy-summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 10px;
    padding: 13px 2px; }
.fy-summary::-webkit-details-marker { display: none; }
.fy-summary:hover .fy-year { color: var(--accent); }
.fy-year { font-family: var(--font-mono), monospace; font-weight: 800; font-size: 15px; color: var(--text); }
.fy-counts { margin-left: auto; display: inline-flex; align-items: center; gap: 12px; font-size: 13px; }
.fy-gold { color: var(--accent); font-weight: 800; white-space: nowrap; }
.fy-silver { color: var(--text); font-weight: 700; white-space: nowrap; }
.fy-total { color: var(--text-dim); font-weight: 600; white-space: nowrap; }
.fy-summary::after { content: "›"; font-size: 19px; line-height: 1; color: var(--text-dim);
    transform: rotate(90deg); transition: transform .2s ease; }
.fy-group:not([open]) > .fy-summary::after { transform: rotate(0); }

/* Final rows — scoreboard layout.
   Outcome signalling mirrors the FIP Radar journey card (.rj-card--win/--loss):
   a tinted card EDGE plus a whisper of wash fading off the top edge. It replaces
   a flat gold/grey left rail that only ever said "title" or "not a title" — grey
   made a hard-fought final and a first-round exit look identical. Rose runs a
   lower alpha than mint because red reads louder at equal opacity; matched
   values would make every loss shout. Colour never works alone: the row already
   says "slog" / "tabte til" in words, and the score carries the tone. */
.ff-list { list-style: none; margin: 0; padding: 2px 0 10px; display: flex; flex-direction: column; gap: 8px; }
.ff-final { --ff-edge: var(--card-border); --ff-wash: transparent;
    display: flex; gap: 12px; align-items: flex-start;
    padding: 12px 14px; border-radius: 12px;
    background: linear-gradient(180deg, var(--ff-wash), rgba(255, 255, 255, 0) 54%), var(--bg-raised);
    border: 1px solid var(--ff-edge);
    transition: border-color .18s; }
.ff-won  { --ff-edge: rgba(74, 222, 128, .22);  --ff-wash: rgba(74, 222, 128, .07); }
.ff-lost { --ff-edge: rgba(255, 107, 107, .19); --ff-wash: rgba(255, 107, 107, .055); }
.ff-badge { flex: none; font-size: 17px; line-height: 1.3; width: 1.3em; text-align: center; }
.ff-round { flex: none; align-self: flex-start; min-width: 42px; text-align: center;
    font-family: var(--font-mono), monospace; font-size: 11px; font-weight: 800;
    color: var(--text-dim); background: var(--card); border: 1px solid var(--card-border);
    border-radius: 6px; padding: 3px 7px; white-space: nowrap; }
.ff-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.ff-head { display: flex; align-items: center; gap: 10px; min-height: 26px; }
.ff-when { font-size: 12px; font-weight: 700; color: var(--text-dim);
  font-variant-numeric: tabular-nums; }
.ff-tourn { font-weight: 700; color: var(--text); }
/* Circuit kicker — the poster-less fallback. A muted mono label, not the old
   white logo chip: the chip had to carry a #fff plate (the source PNG is opaque)
   and repeated identically down every Premier row, so it read as 60 white blocks
   rather than information. Same de-pilled kicker language as the Radar card. */
.ff-circuit { margin-left: auto; flex: none; font-family: var(--font-mono), monospace;
    font-size: 9px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
    color: var(--text-dim); opacity: .75; white-space: nowrap; }
/* Event poster as the row's badge — the crisp portrait thumbnail the FIP Radar
   card uses (.radar-card-poster), scaled to a list row. It replaces a circuit
   logo that was byte-identical on every Premier row: one repeated mark told you
   nothing, the poster tells you WHICH event at a glance. object-fit:cover on a
   ~0.71 poster-aspect box shows the whole poster with minimal crop. Absolutely
   positioned out of flow so a poster row is exactly as tall as a poster-less
   one — a list whose row height flickered with poster coverage would read as a
   rendering bug — and vertically centred, because a row is two or three lines
   tall depending on how long the names are and a top-pinned thumb left all the
   slack pooled underneath it. */
.ff-final:has(.ff-poster) { position: relative; padding-right: 62px; }
.ff-poster { position: absolute; top: 50%; right: 14px; transform: translateY(-50%);
    appearance: none; padding: 0; cursor: zoom-in;
    width: 34px; height: 48px; display: block; overflow: hidden;
    border-radius: 6px; border: 1px solid var(--card-border);
    background: var(--card); box-shadow: 0 3px 10px rgba(0, 0, 0, .35);
    transition: transform .22s cubic-bezier(.2, .8, .3, 1), border-color .22s, box-shadow .22s; }
.ff-poster img { width: 100%; height: 100%; object-fit: cover; object-position: center;
    display: block; }
.ff-poster:hover, .ff-poster:focus-visible {
    transform: translateY(-50%) scale(1.09); border-color: rgba(255, 255, 255, .3);
    box-shadow: 0 8px 22px rgba(0, 0, 0, .5); outline: none; }
.ff-poster:focus-visible { border-color: var(--accent); }
.ff-poster:active { transform: translateY(-50%) scale(1.02); }
@media (prefers-reduced-motion: reduce) {
    .ff-poster { transition: none; }
    .ff-poster:hover, .ff-poster:focus-visible { transform: translateY(-50%); }
}

/* ── Poster viewer ────────────────────────────────────────────────────────
   Tap the thumbnail and the poster grows out of the row to full size. The
   growth is a real FLIP (JS measures both rects and animates the delta), not a
   generic pop-in, so the enlarged print stays tied to the row you clicked —
   the whole point of a lightbox on a dense list is not losing your place.
   Appended to <body> by fip-player.js so it escapes the detail pane's
   stacking + overflow; z-index clears the app's 10050 ceiling. */
.ffpv { position: fixed; inset: 0; z-index: 10060; cursor: zoom-out;
    display: flex; align-items: center; justify-content: center; padding: 5vmin; }
.ffpv[hidden] { display: none; }
.ffpv__scrim { position: absolute; inset: 0; appearance: none; border: 0; padding: 0;
    cursor: zoom-out; background: rgba(6, 10, 18, .82);
    -webkit-backdrop-filter: blur(14px) saturate(.7); backdrop-filter: blur(14px) saturate(.7);
    opacity: 0; transition: opacity .26s ease; }
.ffpv.is-open .ffpv__scrim { opacity: 1; }
.ffpv__fig { position: relative; margin: 0; display: flex; flex-direction: column;
    align-items: center; gap: 14px; max-height: 90vh; }
/* transform-origin top-left so the FLIP delta maths stays a plain rect diff. */
.ffpv__frame { transform-origin: top left; border-radius: 10px; overflow: hidden;
    border: 1px solid rgba(255, 255, 255, .14); background: var(--card);
    box-shadow: 0 30px 90px rgba(0, 0, 0, .7), 0 0 0 1px rgba(0, 0, 0, .4); }
.ffpv__img { display: block; max-width: min(78vw, 620px); max-height: 78vh;
    width: auto; height: auto; }
/* Caption in the site's kicker language: mono, uppercase, tracked out. It fades
   in AFTER the poster has landed — the print is the subject, the label follows. */
.ffpv__cap { display: flex; flex-direction: column; align-items: center; gap: 5px;
    text-align: center; opacity: 0; transform: translateY(6px);
    transition: opacity .3s ease .16s, transform .3s ease .16s; }
.ffpv.is-open .ffpv__cap { opacity: 1; transform: none; }
.ffpv__t { font-size: 15px; font-weight: 700; color: var(--text); }
.ffpv__hint { font-family: var(--font-mono), monospace; font-size: 9px; font-weight: 700;
    letter-spacing: .18em; text-transform: uppercase; color: var(--text-dim); opacity: .8; }
.ffpv__hint i { font-style: normal; }
.ffpv__hint-coarse { display: none; }
@media (hover: none) {
    .ffpv__hint-fine { display: none; }
    .ffpv__hint-coarse { display: inline; }
}
.ffpv__x { position: absolute; top: 16px; right: 18px; appearance: none; cursor: pointer;
    width: 38px; height: 38px; border-radius: 50%; line-height: 1; font-size: 20px;
    color: var(--text-dim); background: rgba(255, 255, 255, .06);
    border: 1px solid rgba(255, 255, 255, .12);
    opacity: 0; transition: opacity .26s ease .1s, color .15s, border-color .15s; }
.ffpv.is-open .ffpv__x { opacity: 1; }
.ffpv__x:hover, .ffpv__x:focus-visible { color: var(--text); border-color: var(--accent); outline: none; }
@media (max-width: 640px) {
    .ffpv { padding: 16px; }
    .ffpv__img { max-width: 88vw; max-height: 70vh; }
    .ffpv__x { top: 10px; right: 10px; }
}
@media (prefers-reduced-motion: reduce) {
    .ffpv__cap, .ffpv__scrim, .ffpv__x { transition: opacity .01s; transform: none; }
}
.ff-match { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; font-size: 13px; }
.ff-pair { color: var(--text-dim); font-weight: 600; }
.ff-pair.is-winner { color: var(--accent); font-weight: 800; }
.ff-vs { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
    color: var(--text-dim); }
.ff-score { font-family: var(--font-mono), monospace; font-size: 12.5px; letter-spacing: .03em;
    color: var(--text-dim); }
/* Step the score's tone with the outcome rather than fading the whole row (a
   blanket opacity muddies the poster and the round chip too). --text-muted, not
   --text-dim, on a loss: dim fails AA on --bg-raised at this size. */
.ff-won .ff-score { color: var(--text); }
.ff-lost .ff-score { color: var(--text-muted); }
/* Tiebreak points raised to a superscript (6⁵-7). Same recipe as .fipdraw-tb /
   .sb-tb in the scoreboard views; declared here because the standalone
   /fip/<slug> page does not load fip-radar.css. line-height:0 keeps the raise
   from nudging the score row's height. */
.ff-tb { font-size: .62em; vertical-align: super; line-height: 0;
    margin-left: 1px; font-weight: 600; }
/* Not-yet-played row — an ongoing tournament's furthest round is scheduled, not
   lost. Amber, matching the Radar's live card (.rj-card--live): green now means
   "won" on this list, so a pending match can no longer borrow it. */
.ff-live { --ff-edge: rgba(255, 181, 71, .26); --ff-wash: rgba(255, 181, 71, .07); }
.ff-round--live { color: var(--accent); border-color: rgba(255, 181, 71, .4);
    background: rgba(255, 181, 71, .08); }
.ff-live-note { display: inline-flex; align-items: center; gap: 6px;
    font-size: 11px; font-weight: 700; color: var(--accent); }
.ff-live-note::before { content: ""; width: 6px; height: 6px; border-radius: 50%;
    background: var(--accent); box-shadow: 0 0 0 0 rgba(255, 181, 71, .55);
    animation: ffLivePulse 1.6s ease-out infinite; }
@keyframes ffLivePulse { to { box-shadow: 0 0 0 6px rgba(255, 181, 71, 0); } }
@media (prefers-reduced-motion: reduce) { .ff-live-note::before { animation: none; } }

/* ══ Tabbed profile (Direction C) ══════════════════════════════════════ */
.fip-tabbar { display: flex; gap: 4px; margin: 22px 0 4px;
    border-bottom: 1px solid var(--card-border); }
.fip-tab { appearance: none; background: none; border: 0; cursor: pointer;
    font: inherit; font-size: 14px; font-weight: 700; color: var(--text-dim);
    padding: 11px 15px; position: relative; transition: color .18s; white-space: nowrap; }
.fip-tab:hover { color: var(--text); }
.fip-tab.is-active { color: var(--accent); }
.fip-tab.is-active::after { content: ""; position: absolute; left: 11px; right: 11px;
    bottom: -1px; height: 2px; border-radius: 2px; background: var(--accent); }
.fip-tabpanel { display: none; padding-top: 18px; }
.fip-tabpanel.is-active { display: flex; flex-direction: column; gap: 16px;
    animation: fipFade .24s ease; }
@keyframes fipFade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.fip-gotab { appearance: none; background: none; border: 0; cursor: pointer; font: inherit;
    font-size: 12px; font-weight: 700; color: var(--accent); }
.fip-empty { color: var(--text-dim); font-size: 14px; padding: 8px 2px; }

/* Rank chart */
.fip-chart-card .fip-chart-wrap { position: relative; height: 220px; }
.fip-chart-wrap canvas { width: 100% !important; height: 100% !important; }

/* Statistik */
.fip-statgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.fip-stat { display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 14px 10px; border-radius: 12px;
    background: var(--bg-raised); border: 1px solid var(--card-border); }
.fip-stat .v { font-family: var(--font-mono), monospace; font-weight: 800; font-size: 22px;
    letter-spacing: -.02em; color: var(--text); }
.fip-stat .v.am, .fip-stat .v.green { color: var(--accent); }
.fip-stat .l { font-size: 11px; color: var(--text-dim); font-weight: 600; }
.fip-wl-meta { display: flex; justify-content: space-between; font-size: 12px;
    color: var(--text-dim); margin: 16px 0 4px; }
.fip-wl { display: flex; height: 9px; border-radius: 6px; overflow: hidden;
    background: var(--card); }
.fip-wl .w { background: var(--accent); }
.fip-wl .l { background: rgba(255, 255, 255, .07); }
.fip-yrow { display: flex; align-items: center; gap: 12px; font-size: 13px;
    padding: 9px 0; border-top: 1px solid var(--card-border); }
.fip-yrow:first-child { border-top: 0; }
.fip-yrow .y { font-family: var(--font-mono), monospace; color: var(--accent); width: 42px; font-weight: 700; }
.fip-yrow .rec { font-family: var(--font-mono), monospace; color: var(--text-dim); width: 58px; }
.fip-yrow .track { flex: 1; height: 6px; border-radius: 4px; background: var(--card); overflow: hidden; }
.fip-yrow .track i { display: block; height: 100%; background: var(--accent); }

/* Partner / opponent rows */
.fip-prow { display: flex; align-items: center; gap: 12px; padding: 10px 0;
    border-top: 1px solid var(--card-border); }
.fip-prow:first-of-type { border-top: 0; }
.fip-ava { flex: none; width: 32px; height: 32px; border-radius: 50%;
    display: grid; place-items: center; font-family: var(--font-mono), monospace;
    font-size: 13px; font-weight: 700; color: var(--accent);
    background: var(--bg-raised); border: 1px solid var(--card-border); text-transform: uppercase; }
.fip-pn { flex: 1; font-weight: 700; color: var(--text); min-width: 0; }
.fip-pwl { font-family: var(--font-mono), monospace; font-size: 13px; color: var(--text-dim); }
.fip-pwl--noera { font-family: inherit; font-style: italic; opacity: 0.6; }

/* ── Makkertidslinje ──────────────────────────────────────────────────────────
   Bars share one origin and scale (left/width are percentages of the baked axis),
   so spans stay comparable across rows at every width. Only the tick count drops
   on mobile — one layout, no second markup path, and no overflow-x rail.

   The cyan is written out rather than referenced as var(--om-blue): that token is
   scoped to .tab-panel[data-tab="fip-radar"] in fip-radar.css, and fip-radar.css
   isn't even loaded on the standalone /fip/<slug> page — so a var() reference
   would silently fall back to nothing. Same #52e1fe the rest of the site uses. */
.fip-tl {
    --tl-fip: var(--accent);
    --tl-pa: #52e1fe;
    --tl-era: rgba(255, 255, 255, 0.028);
    /* Smallest visible bar, and the room the clamp reserves for it at the right
       edge of the track. One token, two rules — see .fip-tl-bar. */
    --tl-nub: 6px;
    /* The stats column is a fixed width, not `auto`, because the axis and the rows
       are separate grid containers that must resolve the SAME column geometry from
       the same template — a var() shared by both is what stops them drifting apart
       later. With `auto` the column sized itself to each row's own copy, so the
       three tracks measured 318.9 / 322.2 / 329.0px and the same percentage landed
       up to 10px apart between rows, silently voiding the one property this layout
       was chosen for. 164px is measured, not guessed: the widest line the seed
       produces is 145.2px and the widest realistic W/L line ("999–999 (1998 kampe)")
       is 156px. Anything longer still wraps rather than overflowing. */
    --tl-stats-w: 164px;
    /* The column template exists ONCE per breakpoint, here, and the two grid
       containers below consume it in a single shared declaration. It used to be
       four copy-pasted literals (axis, row, and both again in the media query)
       held together only by a comment asking for discipline — and discipline is
       exactly what failed: the axis silently diverging from the row is the bug
       this panel already shipped once. Now one edit cannot desync from another,
       because there is only one place to edit. */
    --tl-grid: 32px minmax(0, 1fr) 1fr var(--tl-stats-w);
    /* Mobile: the stats column is a flat 45% share instead of `auto`. With `auto` the
       secondary column outbid the primary one — a realistic W/L line
       ("999–999 (1998 kampe)" ≈ 144px) took its content width and left the NAME
       43px at 320px and 113px at 390px, clipping 23 of 25 names. The name column
       is the row's identity; it gets the majority share and the mono stats line
       wraps instead.
       `minmax(0, 45%)` reads like a ceiling but is not one: the `1fr` name column
       absorbs whatever is left, so the stats column is never asked to shrink below
       its 45% max and the `0` floor never comes into play. It resolves to exactly
       45% at every width — measured 109px of 242 at 320 and 141px of 313 at 390,
       regardless of what the stats line contains. That determinism is the point:
       a content-sized column would differ row to row, and equalTracks only holds
       because this one does not. The chart spans 2/-1, so every track is the same
       box in the axis and in every row. */
    --tl-grid-mobile: 32px minmax(0, 1fr) minmax(0, 45%);
    /* Which column(s) the chart occupies, named once and consumed together by the
       ticks, the era wash and every bar track — so the axis and the bars cannot
       land in different columns, which is the precise shape of both bugs found in
       this panel so far. Mobile ends at `-1` and desktop at an explicit `4`: never
       leave an end line `auto`, because for the abspos wash `auto` resolves to the
       container's padding edge, not the next line. */
    --tl-chart-col: 3 / 4;
    --tl-chart-col-mobile: 2 / -1;
}

/* Axis and rows are separate grid containers that must resolve IDENTICAL columns,
   or the ticks and the bars are two coordinate spaces: a tick's `left: N%` against
   the full panel width while a bar's `left: N%` is against the narrower, offset
   track column, which put 2021's label 142px from a 2021 bar at 1200px. One
   declaration for both elements, one column-gap for both (they must match too, or
   the boxes shift apart). Measured by axisAligned / equalTracks / eraAligned. */
.fip-tl-axis, .fip-tl-row { display: grid; grid-template-columns: var(--tl-grid);
    column-gap: 12px; }
.fip-tl-ticks, .fip-tl-era, .fip-tl-track { grid-column: var(--tl-chart-col); }

.fip-tl-axis { position: relative; height: 18px; margin: 2px 0 6px; }
.fip-tl-ticks { position: relative; height: 100%; }
.fip-tl-tick { position: absolute; transform: translateX(-50%);
    font-family: var(--font-mono), monospace; font-size: 10px;
    letter-spacing: 0.08em; color: var(--text-dim); white-space: nowrap; }
/* The Premier Padel era wash runs from its start to the right edge of the chart
   column, behind the rows. It is absolutely positioned but still carries a grid
   placement: an abspos child of a grid container is positioned against its grid
   area, which is how `left: N%` here lands on the same scale as the bars.

   Its placement comes from --tl-chart-col, whose end line is always explicit. A
   bare `grid-column: 3` stretched this wash's containing block from the chart
   column's left edge to the panel's right edge — it measured 860.3px where 2021
   is at 782.1px. That shipped green once, because axisAligned only inspects the
   ticks against the tracks; eraAligned now covers the wash.
   Inert decoration: aria-hidden in the markup. */
.fip-tl-era { position: absolute; top: 0; right: 0; bottom: 0;
    background: var(--tl-era); pointer-events: none; }

/* Every row keeps its top border, including the first: .fip-tl-axis is the first
   div sibling, so no row is :first-of-type and the rule that used to try to strip
   it never matched. The line under the axis strip is wanted — it reads as the
   divider between the scale and the rows. */
.fip-tl-row { align-items: center; row-gap: 12px; padding: 10px 0;
    border-top: 1px solid var(--card-border); }

.fip-tl-id { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fip-tl-name { font-weight: 700; color: var(--text); overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }
.fip-tl-name a { color: inherit; text-decoration: none; }
.fip-tl-name a:hover { color: var(--accent); }
.fip-tl-kicker { font-family: var(--font-mono), monospace; font-size: 10px;
    letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); }

.fip-tl-track { position: relative; height: 8px; border-radius: 99px;
    background: var(--card-border); }
/* The nub clamp. `min-width: var(--tl-nub)` is what keeps a one-month partnership
   visible instead of a 0.4% sliver, and it is the reason the bar can overhang its
   track: a partnership starting in December of axis.to sits at ~99% of the axis,
   where a 6px box no longer fits. So `left` is capped at "one nub short of the
   right edge" — the bar then ends flush with the track, fully visible, and
   rowOverflow stays <= 0. Both halves read the same token, so the nub width
   cannot drift from the room reserved for it. The percentage arrives as
   --tl-bar-left from the template because CSS min() cannot be applied to a value
   an inline `left` already resolved. */
.fip-tl-bar { position: absolute; top: 0; bottom: 0; border-radius: 99px;
    left: min(var(--tl-bar-left, 0%), calc(100% - var(--tl-nub)));
    min-width: var(--tl-nub); }
.fip-tl-bar--fip { background: var(--tl-fip); }
.fip-tl-bar--padelapi { background: var(--tl-pa); }

.fip-tl-stats { display: flex; flex-direction: column; align-items: flex-end;
    gap: 1px; text-align: right; }
.fip-tl-wl { font-family: var(--font-mono), monospace; font-size: 13px;
    color: var(--text); }
.fip-tl-hon { font-family: var(--font-mono), monospace; font-size: 11px;
    color: var(--text-dim); }
.fip-tl-note { font-size: 11px; font-style: italic; color: var(--text-dim);
    opacity: 0.75; }

.fip-tl-legend { display: flex; flex-wrap: wrap; gap: 6px 18px; padding-top: 12px;
    margin-top: 4px; border-top: 1px solid var(--card-border);
    font-size: 11px; color: var(--text-muted); }
.fip-tl-legend span { display: inline-flex; align-items: center; gap: 6px; }
.fip-tl-legend em { color: var(--text-dim); font-style: normal; }
.fip-tl-sw { width: 14px; height: 6px; border-radius: 99px; flex: none; }
.fip-tl-sw--fip { background: var(--tl-fip); }
.fip-tl-sw--padelapi { background: var(--tl-pa); }

/* Mobile: the track moves under the name so neither gets squeezed, and only the
   first and last ticks survive. 768px, not 640px — the page container caps this
   panel's width until 768px, the same reason the tab rail's breakpoint is 767.

   The shape here is "ava id stats" over ". track track": the chart drops to its
   own row under the name so neither gets squeezed, and it spans everything right
   of the avatar. Both grid containers swap template in one declaration and the
   chart swaps column in one more, so the axis cannot be left on the desktop
   template while the rows move — which is how it drifted out of the chart column
   before. The stats column is proportional rather than fixed here: a fixed 164px
   would leave the name ~27px at 320px wide, and a bare `auto` starved it to 43px.
   `minmax(0, 45%)` resolves to a flat 45% — the `1fr` name column takes the
   remainder, so the stats column is never squeezed under its max (see
   --tl-grid-mobile) — which is what keeps every track identical whatever a row's
   stats line says. The chart spans columns 2–3, so its box is the panel minus the
   44px avatar gutter, in the axis and in every row alike. */
@media (max-width: 767px) {
    .fip-tl-axis, .fip-tl-row { grid-template-columns: var(--tl-grid-mobile); }
    .fip-tl-ticks, .fip-tl-era, .fip-tl-track {
        grid-column: var(--tl-chart-col-mobile); }
    .fip-tl-row { row-gap: 8px; }
    /* Scoped to this panel: the unscoped `.fip-ava` rule this replaces also matched
       the "Faste makkere" and H2H avatars, and was inert there only because those
       parents happen to be flex containers. */
    .fip-tl-row .fip-ava { grid-row: 1; grid-column: 1; }
    .fip-tl-id { grid-row: 1; grid-column: 2; }
    .fip-tl-stats { grid-row: 1; grid-column: 3; }
    .fip-tl-track { grid-row: 2; }
    .fip-tl-tick:not(:first-child):not(:last-child) { display: none; }
    .fip-tl-wl { font-size: 12px; }
}

/* Head-to-head */
.fip-h2h-search { width: 100%; box-sizing: border-box; font: inherit; font-size: 15px;
    color: var(--text); background: var(--bg-raised); border: 1px solid var(--card-border);
    border-radius: 12px; padding: 10px 14px; }
.fip-h2h-search::placeholder { color: var(--text-dim); }
.fip-h2h-search:focus { outline: none; border-color: var(--accent-border); }
.fip-h2h-out { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.fip-h2h-pick { appearance: none; text-align: left; cursor: pointer; font: inherit;
    font-size: 14px; font-weight: 600; color: var(--text);
    background: var(--bg-raised); border: 1px solid var(--card-border);
    border-radius: 10px; padding: 10px 14px; transition: border-color .15s; }
.fip-h2h-pick:hover { border-color: var(--accent-border); }
.fip-h2h-card { padding: 16px; border-radius: 14px;
    background: var(--bg-raised); border: 1px solid var(--card-border); }
.fip-h2h-score { display: flex; align-items: center; justify-content: center; gap: 14px;
    font-family: var(--font-mono), monospace; font-weight: 800; font-size: 16px; color: var(--text); }
.fip-h2h-score b { font-size: 30px; letter-spacing: -.02em; }
.fip-h2h-score .nm { font-size: 13px; font-weight: 700; color: var(--text-dim); flex: 1; text-align: center; }

/* H2H partner filter chips */
.fip-h2h-filter { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
.fip-h2h-chip { appearance: none; cursor: pointer; font: inherit; font-size: 13px;
  font-weight: 600; color: var(--text-dim); background: var(--panel-2, rgba(255,255,255,.04));
  border: 1px solid var(--border, rgba(255,255,255,.12)); border-radius: 999px;
  padding: 6px 12px; display: inline-flex; align-items: center; gap: 6px;
  transition: border-color .15s, color .15s, background .15s; }
.fip-h2h-chip:hover { border-color: var(--accent-border); color: var(--text); }
.fip-h2h-chip.is-active { color: var(--text); border-color: var(--accent-border);
  background: rgba(255, 181, 71, .14); }
.fip-h2h-chip .c { font-variant-numeric: tabular-nums; font-size: 11.5px;
  color: var(--text-dim); font-weight: 700; }
.fip-h2h-chip.is-active .c { color: var(--text); }

/* H2H by-year table */
.fip-h2h-years { width: 100%; border-collapse: collapse; margin: 14px 0 6px;
  font-size: 13.5px; }
.fip-h2h-years th { text-align: right; font-weight: 700; font-size: 11px;
  letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim);
  padding: 0 0 6px; border-bottom: 1px solid var(--border, rgba(255,255,255,.12)); }
.fip-h2h-years th:first-child { text-align: left; }
.fip-h2h-years td { padding: 7px 0; border-bottom: 1px solid rgba(255,255,255,.06);
  text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.fip-h2h-years td.yr { text-align: left; font-weight: 700; }
.fip-h2h-years td.pct { color: var(--text-dim); }
.fip-h2h-years tr:last-child td { border-bottom: none; }

/* ── H2H highlight cards + Rivaler leaderboard ─────────────────────────── */
.fip-hlcards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.fip-hlcard { display: flex; flex-direction: column; gap: 4px;
    padding: 14px 16px; border-radius: 12px;
    background: var(--card); border: 1px solid var(--card-border); }
/* Same mint/rose tokens as the result rows: once green means "won" on this tab,
   the favourite opponent can't keep wearing gold next to a rose nemesis — two
   cards about the same axis have to sit on the same scale. Rose stays the lower
   alpha (red shouts at equal opacity). */
.fip-hlcard.is-nemesis { border-color: rgba(255, 107, 107, .30);
    background: linear-gradient(180deg, rgba(255, 107, 107, .055), rgba(255, 255, 255, 0) 60%), var(--card); }
.fip-hlcard.is-fav { border-color: rgba(74, 222, 128, .30);
    background: linear-gradient(180deg, rgba(74, 222, 128, .07), rgba(255, 255, 255, 0) 60%), var(--card); }
.fip-hlcard__k { font-size: 12px; font-weight: 700; letter-spacing: .04em;
    color: var(--text-dim); }
.fip-hlcard__n { font-size: 16px; font-weight: 700; color: var(--text); }
.fip-hlcard__r { font-size: 13px; color: var(--text-dim); }

.fip-rivals { list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; }
.fip-rival-row { display: flex; align-items: center; gap: 12px;
    padding: 10px 4px; border-bottom: 1px solid var(--card-border);
    cursor: pointer; transition: background .15s; }
.fip-rival-row:last-child { border-bottom: 0; }
.fip-rival-row:hover, .fip-rival-row:focus-visible {
    background: var(--bg-raised); outline: none; }
.fip-rival-n { flex: 1; font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fip-rival-r { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }
.fip-rival-pct { font-variant-numeric: tabular-nums; color: var(--text-dim);
    min-width: 42px; text-align: right; }

/* ── Tab rail: a fixed 4-up grid below 768px. It used to be a horizontal
   scroller, but the four tabs are 450px of content and the page container caps
   the bar at 444px all the way to 768px — so on every phone and small tablet
   the rail was a drag surface. Fractional columns cannot overflow. Short H2H
   label + hidden count pill come from player.css, loaded on this page too. ── */
@media (max-width: 767px) {
    .fip-tabbar { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0;
        overflow-x: clip; }
    .fip-tab { min-width: 0; display: inline-flex; align-items: center;
        justify-content: center; font-size: 12px; padding: 10px 2px; }
    .fip-tab.is-active::after { left: 5px; right: 5px; }
}

/* ── Mobile: tighter grids ─────────────────────────────────────────────────── */
@media (max-width: 640px) {
    .gd-kpis { grid-template-columns: repeat(2, 1fr); }
    .fip-statgrid { grid-template-columns: repeat(2, 1fr); }
    .fip-hlcards { grid-template-columns: 1fr; }
}
