/**
 * Gymnastics Plus - Profile Page Styles
 * 
 * @package Gymnastics_Plus
 * @version 2.3.16
 * 
 * UPDATED: 2025-02-06
 * - Fixed video menu z-index to sit above play overlay (z-index 10 vs 5)
 * - Prevents edit/delete menu clicks from triggering video playback
 * 
 * PREVIOUS: 2025-12-30
 * - Added 16px top margin for gap below navigation
 * - Fixed video menu dropdown click behavior
 * 
 * PREVIOUS: 2025-12-28
 * - Added Scout-style video cards with thumbnail backgrounds
 * - Added video playback modal styles
 * - Improved video card badges and score display
 * 
 * PERFORMANCE NOTES:
 * - CSS variables for consistency and easy theming
 * - Mobile-first media queries
 * - Minimal specificity for fast parsing
 * - Hardware-accelerated transforms
 * - Optimized for 20k+ concurrent users
 */
/* ========================================
   CSS VARIABLES (Single source of truth)
   ======================================== */
:root {
    /* Colors — D2 (2026-07-23) de-fork: repointed onto gp-base.css Tier-2 semantics so this whole
       file (every consumer of these local vars) resolves dark-capable through the shared token
       seam. Byte-identical in light: --gp-card-bg / --gp-accent-gold map to an EXISTING Tier-2
       token at the exact same value; --gp-border-color / --gp-text-primary / --gp-text-secondary /
       --gp-bg-gray map to NEW Tier-2 semantics added in gp-base.css whose light value is the exact
       original hex (see gp-base.css's "D2 legacy-fork reconciliation" comment). The ONE declaration
       in this file that referenced --gp-text-primary as a solid FILL (not text) was decoupled first
       (hardcoded to its literal original value) so this retokenization doesn't invert it — see
       .gp-filter-btn.active below (--gp-text-secondary had no such fill usage, safe as-is).
       Left un-retokenized (flagged, no exact Tier-2 match / no Tier-2 equivalent at all): --gp-card-shadow
       (multi-layer, no Tier-2 shadow match), --gp-accent-gold-hover (c9a64d vs Tier-1 c9a64e — 1-digit
       drift), --gp-danger/--gp-success/--gp-link (each a distinct legacy shade, no exact Tier-1/2 match). */
    --gp-card-bg: var(--gp-color-surface);
    --gp-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.05);
    --gp-card-radius: 12px;
    --gp-card-padding: 20px;
    --gp-card-gap: 16px;
    --gp-border-color: var(--gp-color-border-profile);
    --gp-text-primary: var(--gp-color-text-profile);
    --gp-text-secondary: var(--gp-color-text-muted-profile);
    --gp-accent-gold: var(--gp-color-accent);
    --gp-accent-gold-hover: #c9a64d;
    /* R0 (2026-07-26) — the text-role counterpart, same local-alias convention as the line above.
       --gp-accent-gold is a FILL (it backs ~14 pills, bars and buttons in this file) and reads at
       1.89:1 as ink on the white card surface. The two rules in this file that painted READ TEXT
       with it now use this instead; the star glyph, the competition-row SVG, the progress stroke
       and the dark video-modal value deliberately keep the fill gold. */
    --gp-accent-gold-text: var(--gp-color-accent-text);
    --gp-bg-gray: var(--gp-color-bg-profile);
    --gp-danger: #e74c3c;
    --gp-success: #27ae60;
    --gp-link: #1877f2;

    /* Responsive Content Widths */
    --gp-content-max: 600px;      /* Max width for centered content on touch devices */
    --gp-content-wide: 900px;     /* Max width for desktop */
    --gp-btn-max: 280px;          /* Max button width */
    
    /* Responsive Spacing */
    --gp-space-xs: 4px;
    --gp-space-sm: 8px;
    --gp-space-md: 16px;
    --gp-space-lg: 24px;
    --gp-space-xl: 32px;
}
/* ========================================
   PROFILE WRAPPER
   ======================================== */
.gp-profile-wrapper {
    max-width: 900px;
    margin: 16px auto 0 auto;
    background: var(--gp-bg-gray);
    font-family: 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif;
    padding-bottom: 40px;
    min-height: 100vh;
}
/* ========================================
   CARD COMPONENT (Reusable)

   SCOPED TO THIS PAGE'S OWN WRAPPER, 2026-09-09. This file forks the frozen
   .gp-card from assets/css/gp-core.css, and the fork was UNSCOPED, which on
   the app door is not a style opinion but a leak. The shell soft-navigates by
   swapping the view region and leaves the <head> alone, so a stylesheet
   enqueued for one screen keeps applying to every screen visited after it.
   gp_enqueue_profile_assets() loads this file on is_singular('gymnast_profile'),
   which includes the APP profile - a template that uses .gp-card ZERO times -
   and from then on the padding below landed on the Recruiting Portal's and the
   College Tracker's cards, pushing their black section headers 12px in from
   the card edge instead of letting them cap it.

   MEASURED on dev at 390 before the fix: Portal group card padding 0px opened
   directly, 12px after a Profile visit, with the ink band inset 12/12/12; same
   on the Tracker. Owner report: "the recruiting portal looks weird, and it's
   supposed to look similar to the profile", and "doesn't look like this all of
   the time, but sometimes it messes up".

   .gp-profile-wrapper is the CLASSIC profile's own top-level container
   (page-templates/single-gymnast_profile.php), and every .gp-card on that page
   is inside it (measured: 8 of 8 rendered, at desktop and at phone). It exists
   on no other screen, so the fork can no longer travel.

   :where() AND NOT A PLAIN DESCENDANT, and the difference is not cosmetic. A
   plain `.gp-profile-wrapper .gp-card` raises this fork from one class to two,
   and a scoping change must not also be a cascade change. Caught by measuring
   rather than by reading: with the plain form, all 8 cards on the phone moved
   from a 12px radius to 10px, because gp-profile.css's own max-width 480 block
   started beating a single-class rule in another stylesheet that had been
   winning on order. :where() contributes ZERO specificity, so these rules keep
   the exact weight and position they have today and only gain the requirement
   to sit inside the profile.

   The right long-term fix is for this page to stop forking the library card at
   all; this is the containment, not the cure.
   ======================================== */
:where(.gp-profile-wrapper) .gp-card {
    background: var(--gp-card-bg);
    border-radius: var(--gp-card-radius);
    box-shadow: var(--gp-card-shadow);
    padding: var(--gp-card-padding);
    margin-bottom: var(--gp-card-gap);
}
.gp-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--gp-border-color);
}
.gp-card-title { /* heading ramp: h6 */
    font-size: var(--gp-h6-size);
    line-height: var(--gp-h6-line);
    font-weight: var(--gp-h6-weight);
    letter-spacing: var(--gp-h6-tracking);
    color: var(--gp-text-primary);
    margin: 0;
}
.gp-card-body {
    color: var(--gp-text-primary);
}
.gp-card-footer {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--gp-border-color);
}
/* ========================================
   PROFILE HEADER
   ======================================== */
.gp-profile-header {
    background: var(--gp-card-bg);
    border-radius: 0 0 var(--gp-card-radius) var(--gp-card-radius);
    box-shadow: var(--gp-card-shadow);
    margin-bottom: var(--gp-card-gap);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}
.gp-cover-photo {
    width: 100%;
    height: 200px;
    overflow: hidden;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.gp-cover-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.gp-header-content {
    display: flex;
    align-items: flex-end;
    gap: 24px;
    padding: 24px 30px 30px 30px;
    margin-top: -60px;
    position: relative;
    z-index: 1;
}
.gp-profile-header:not(.has-cover) .gp-header-content {
    margin-top: 0;
    padding-top: 30px;
}
.gp-profile-photo {
    width: 176px;
    height: 176px;
    border-radius: 50%;
    /* White ring + gray backing removed entirely (owner, 2026-07-14) — the photo circle
       sits directly on the cover; the soft shadow alone separates it. */
    border: none;
    overflow: hidden;
    background: transparent;
    flex-shrink: 0;
    box-shadow: 0 2px 12px rgba(0,0,0,0.2);
}
.gp-profile-photo img {
    width: 100%;
    height: 100%;
    /* Image is already circular with transparent corners - just fill the space */
    object-fit: cover;
    object-position: center center;
}
/* No real photo — the white ring/box is a REAL-PHOTO treatment only; the purple
   initials tile (.gp-profile-initial) needs no white chrome behind it. */
.gp-profile-photo--ph {
    border: none;
    background: transparent;
    box-shadow: none;
}
.gp-profile-photo-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--gp-accent-gold);
    color: #000;
    font-size: 72px;
    font-weight: 700;
}
.gp-profile-info {
    flex: 1;
    /* The NAME owns its line (owner, 2026-07-14): reserve real width for the info column
       so the actions cluster (badges/buttons) wraps below instead of starving the h1 into
       early ellipsis. Ellipsis remains only for truly extreme names. */
    min-width: min(28ch, 100%);
    padding-bottom: 8px;
}
.gp-name-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 6px;
}
.gp-profile-name { /* heading ramp: h1 */
    /* Slightly below the h1 ramp so realistic long names fit the ~396px profile info
       column on one line (the full token size overflowed ~24-char names by a few px). */
    font-size: clamp(24px, 2.4vw, 30px);
    line-height: var(--gp-h1-line);
    font-weight: var(--gp-h1-weight);
    letter-spacing: var(--gp-h1-tracking);
    margin: 0;
    color: var(--gp-text-primary);
    /* Name must never wrap — a wrapped 2nd line grew up into the cover overlap
       (margin-top:-60px + overflow:hidden) and got clipped. One line; fill the info
       column (width:100% — the name-row is align-items:flex-start, so without this the
       h1 shrink-wraps and ellipsizes early with empty space to its right); ellipsis only
       when the name truly exceeds the available width. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 100%;
}
/* Recruiting Status Badges */
.gp-recruiting-badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 12px;
    border-radius: 100px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
    white-space: nowrap;
}
.gp-status-active {
    background: rgba(52, 199, 89, 0.12);
    color: #248a3d;
}
.gp-status-committed {
    background: rgba(0, 122, 255, 0.10);
    color: #0055d4;
}
.gp-status-inactive {
    background: rgba(142, 142, 147, 0.12);
    color: #6e6e73;
}
.gp-status-not-recruiting {
    background: rgba(255, 149, 0, 0.10);
    color: #c45d00;
}

/* Parent "managing on behalf" context cue — shown on the child's profile when a
   linked parent is the editor (B2 parent manage-on-behalf). Solid saturated
   info-blue per the de-gold / no-mist design rule; an informational chip, not a
   CTA (gold stays reserved for CTAs). */
.gp-managing-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    border-radius: 100px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
    white-space: nowrap;
    background: var(--gp-info);
    color: var(--gp-white);
}
.gp-managing-pill svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* Recruiting Status Dropdown */
.gp-recruiting-select {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='2.5' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    padding-right: 40px;
    cursor: pointer;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.gp-recruiting-hint {
    margin-top: 6px;
    font-size: 12px;
    color: #8e8e93;
    transition: color 0.15s ease;
}

/* Legacy class — keep for backward compat with any cached HTML */
.gp-recruitment-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(46, 204, 113, 0.15);
    color: var(--gp-success);
    padding: 4px 12px;
    border-radius: 20px;
    font-size: 13px;
    font-weight: 600;
}
.gp-profile-meta {
    display: flex;
    gap: 16px;
    flex-wrap: nowrap;
    align-items: center;
    color: var(--gp-text-secondary);
    font-size: 15px;
    margin-bottom: 10px;
}
.gp-profile-meta span {
    display: flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
    flex-shrink: 0; /* never squeeze an item so its text breaks ("Class of"/"2026"); when
                       it doesn't fit, the row wraps the whole item to the next line. */
}
.gp-events-badges {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.gp-event-badge {
    display: inline-flex;
    align-items: center;
    background: var(--gp-bg-gray);
    color: var(--gp-text-primary);
    padding: 4px 12px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
}
.gp-event-badge.gp-all-around {
    background: var(--gp-accent-gold);
    color: #000;
    font-weight: 600;
}
/* ========================================
   GYMNASTICS CARD (Personal Bests + Accomplishments) — profile About tab
   ======================================== */
.gp-gym-block { margin-bottom: 22px; }
.gp-gym-block:last-child { margin-bottom: 0; }
.gp-gym-subtitle {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 700;
    color: var(--gp-text-secondary);
    margin-bottom: 12px;
}
/* Level pill — now lives in the profile header band next to the name (public). */
.gp-header-level-pill {
    display: inline-flex;
    align-items: center;
    background: var(--gp-accent-gold);
    color: #000;
    border-radius: 20px;
    padding: 3px 12px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
    vertical-align: middle;
    margin-left: 10px;
}
/* Level color tiers — soft "mist" tint + matching-color text (like the Active badge),
   EXCEPT Level 10 which keeps the solid gold pop as the standout tier. */
.gp-header-level-pill.gp-level-tier-9     { background: rgba(37, 99, 235, 0.12); color: #1d4ed8; }
.gp-header-level-pill.gp-level-tier-10    { background: var(--gp-accent-gold); color: #000; }
.gp-header-level-pill.gp-level-tier-elite { background: rgba(109, 40, 217, 0.12); color: #6d28d9; }
/* Active/Inactive recruiting status — editor-only chip in the header actions row. */
.gp-profile-actions .gp-recruiting-badge {
    font-size: 11px;
    padding: 4px 10px;
    border-radius: 14px;
    font-weight: 600;
    align-self: center;
    white-space: nowrap;
}
.gp-gym-pb-grid {
    display: grid;
    /* All five events on one row on desktop (AA no longer drops below). */
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 10px;
}
@media (max-width: 700px) {
    .gp-gym-pb-grid {
        grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
    }
}
.gp-gym-pb-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: var(--gp-bg-gray);
    border-radius: 8px;
    padding: 10px 12px;
}
.gp-gym-pb-label {
    font-size: 12px;
    color: var(--gp-text-secondary);
    font-weight: 500;
}
.gp-gym-pb-score {
    font-size: 20px;
    font-weight: 700;
    color: var(--gp-text-primary);
    font-variant-numeric: tabular-nums;
}
.gp-gym-pb-item--aa { background: var(--gp-accent-gold); }
.gp-gym-pb-item--aa .gp-gym-pb-label,
.gp-gym-pb-item--aa .gp-gym-pb-score { color: #000; }
.gp-gym-acc-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.gp-gym-acc-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: var(--gp-bg-gray);
    border-radius: 8px;
    padding: 10px 12px;
}
.gp-gym-acc-star { font-size: 18px; line-height: 1.3; flex-shrink: 0; color: var(--gp-accent-gold); }
.gp-gym-acc-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.gp-gym-acc-title { font-size: 15px; font-weight: 600; color: var(--gp-text-primary); }
.gp-gym-acc-meta { font-size: 13px; color: var(--gp-text-secondary); }
/* Achievements (Accomplishments) progressive disclosure: show the first 5, collapse
   the rest behind a "Show all (N)" ghost toggle. Pure CSS hide; js/gp-profile.js
   (initAchievementsDisclosure) adds/removes the --collapsed modifier and injects the
   .gp-btn ghost toggle. No button is injected when there are <= 5. */
.gp-gym-acc-list--collapsed .gp-gym-acc-item:nth-child(n+6) {
    display: none;
}
.gp-gym-acc-toggle {
    margin-top: 10px;
}

/* Accomplishments repeater — Edit Profile → Gymnastics tab */
.gp-acc-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.gp-acc-row {
    display: grid;
    grid-template-columns: 1fr 130px 110px 92px auto;
    gap: 8px;
    align-items: center;
}
.gp-acc-row .gp-form-input,
.gp-acc-row .gp-form-select { margin: 0; }
.gp-acc-remove {
    width: 34px;
    height: 34px;
    border: none;
    border-radius: 8px;
    background: var(--gp-bg-gray);
    color: var(--gp-text-secondary);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    flex-shrink: 0;
}
.gp-acc-remove:hover { background: var(--gp-danger, #e74c3c); color: #fff; }
.gp-acc-add { margin-top: 4px; }
@media (max-width: 600px) {
    .gp-acc-row {
        grid-template-columns: 1fr;
        gap: 8px;
        padding: 12px;
        background: var(--gp-bg-gray);
        border-radius: 10px;
    }
    .gp-acc-remove { justify-self: end; }
}
.gp-profile-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-self: flex-end;
}
/* ========================================
   BUTTONS
   ======================================== */
.gp-btn {
    padding: 10px 20px;
    border-radius: 8px;
    border: none;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background-color 0.2s ease, transform 0.1s ease;
    font-family: inherit;
}
.gp-btn:active {
    transform: scale(var(--gp-press-scale-button)); /* F2 (2026-07-26): converged onto the shared token, was a local 0.98. NOTE: this whole .gp-btn rule is a pre-existing full local fork of the frozen gp-core.css class (padding/colors differ) — out of this Size-S slice's scope to de-fork; only the press scale is converged here. */
}
.gp-btn-primary {
    background: var(--gp-accent-gold);
    color: #000;
}
.gp-btn-primary:hover {
    background: var(--gp-accent-gold-hover);
}
.gp-btn-secondary {
    background: #e4e6eb;
    color: var(--gp-text-primary);
}
.gp-btn-secondary:hover {
    background: #d8dadf;
}
/* Dark-mode readability (UB, 2026-07-25 wave 3) — --gp-text-primary above is already
   dark-aware (aliased onto --gp-color-text-profile), but the light-gray literal
   background just above has no exact Tier-2 match, so it stayed a light-gray chip
   under the now-light-colored label text: near-invisible ink-on-light-on-a-dark-panel.
   Light is untouched (the declaration above, unchanged). */
[data-theme="dark"] .gp-btn-secondary {
    background: var(--gp-color-surface-2);
    color: var(--gp-color-text);
}
[data-theme="dark"] .gp-btn-secondary:hover {
    background: var(--gp-color-border);
}
.gp-btn-danger {
    background: var(--gp-danger);
    color: #fff;
}
.gp-btn-danger:hover {
    background: #c0392b;
}
/* Cancel / Save / Delete — the Edit Profile, Add Video, and Confirm Delete modal
   footers all use these three classes, but none of them had ANY base style
   anywhere in the codebase: they rendered as plain native <button>s (a light-gray
   UA default that happened to look tolerable on a white modal, but went to a
   near-invisible gray box on the new dark panel). Adding real styling here fixes
   both themes at once, following this file's own established button/token
   conventions — .gp-btn-cancel borders/inks off the same dark-aware --gp-color-*
   semantics as .gp-form-input, so it needs no separate dark override; .gp-btn-save
   reuses the exact .gp-btn-primary gold-fill/black-ink pairing (gold is a constant
   accent in both themes, already proven not to need one either). */
.gp-btn-cancel {
    padding: 11px 20px;
    border-radius: 10px;
    border: 1px solid var(--gp-color-border);
    background: transparent;
    color: var(--gp-text-secondary);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 0.2s ease;
}
.gp-btn-cancel:hover {
    /* NOT --gp-bg-gray: .gp-modal-footer already sits on that exact color, so a
       transparent button hovering to the same value would show no feedback at all. */
    background: var(--gp-color-border);
}
.gp-btn-save {
    padding: 11px 20px;
    border-radius: 10px;
    border: 1px solid transparent;
    background: var(--gp-accent-gold);
    color: var(--gp-black);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 0.2s ease;
}
.gp-btn-save:hover {
    background: var(--gp-accent-gold-hover);
}
.gp-btn-delete {
    background: transparent;
    color: var(--gp-danger);
    font-family: inherit;
    cursor: pointer;
}
.gp-btn-delete:hover {
    background: rgba(231, 76, 60, 0.08);
}
/* ========================================
   TAB NAVIGATION
   ======================================== */
.gp-tab-navigation {
    display: flex;
    background: var(--gp-card-bg);
    border-radius: var(--gp-card-radius);
    box-shadow: var(--gp-card-shadow);
    margin-bottom: var(--gp-card-gap);
    padding: 4px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.gp-tab-btn {
    flex: 1;
    padding: 14px 20px;
    border: none;
    background: none;
    font-size: 15px;
    font-weight: 600;
    color: var(--gp-text-secondary);
    cursor: pointer;
    border-radius: 8px;
    transition: background-color 0.2s ease, color 0.2s ease;
    white-space: nowrap;
    font-family: inherit;
    min-width: 0;
}
.gp-tab-btn:hover {
    background: var(--gp-bg-gray);
}
.gp-tab-btn.active {
    background: var(--gp-bg-gray);
    color: #1a1a2e;
    font-weight: 600;
}
/* Dark-mode active-tab readability (UB, 2026-07-24) — the light declaration above is untouched
   (--gp-bg-gray already resolves dark via --gp-color-bg-profile, but the raw 1a1a2e ink never did,
   so a dark page rendered ink-on-dark for the selected tab, e.g. "About"). This ADDS a dark-only
   override with the same elevated selected-fill pair used by the portal sidebar + College Tracker
   toggle. See gp-base.css's --gp-color-fill-selected / --gp-color-on-fill-selected for the token +
   contrast numbers. */
[data-theme="dark"] .gp-tab-btn.active {
    background: var(--gp-color-fill-selected);
    color: var(--gp-color-on-fill-selected);
}
/* Per-tab video count chip (Routines/Skills/Upgrades). Deliberate inverse-ink fill via
   Tier-2 tokens — a solid dark chip + light text in light mode, flipping to a light chip
   + dark text in dark mode — so it stays high-contrast on BOTH the transparent inactive
   tab and the gray active tab, in either theme. Not gold (brand-only), not danger-red
   (no alert), not a pale wash or bare-gray text. Shown only when count > 0. */
.gp-tab-btn__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 6px;
    margin-left: 4px;
    border-radius: 9px;
    background: var(--gp-color-text);
    color: var(--gp-color-text-inverse);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    vertical-align: middle;
}
/* ========================================
   TAB CONTENT
   ======================================== */
.gp-tab-content {
    display: none;
    padding: 0 16px;
}
.gp-tab-content.active {
    display: block;
}
/* ========================================
   FILTER BUTTONS
   ======================================== */
.gp-subtab-navigation {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: var(--gp-card-gap);
}
.gp-filter-buttons {
    display: flex;
    flex: 1;
    background: var(--gp-card-bg);
    border-radius: var(--gp-card-radius);
    padding: 4px;
    box-shadow: var(--gp-card-shadow);
}
.gp-filter-btn {
    flex: 1;
    padding: 12px 16px;
    border: none;
    background: none;
    font-size: 14px;
    font-weight: 600;
    color: var(--gp-text-secondary);
    cursor: pointer;
    border-radius: 8px;
    transition: background-color 0.2s ease, color 0.2s ease;
    font-family: inherit;
}
.gp-filter-btn:hover {
    background: var(--gp-bg-gray);
}
.gp-filter-btn.active {
    /* D2: decoupled from --gp-text-primary (2026-07-23) so that variable can become dark-aware
       for its TEXT role below without breaking this always-dark "active pill" fill (matches the
       un-retokenized precedent elsewhere, e.g. gp-core's .gp-nav-item.active). Literal value is
       byte-identical to what --gp-text-primary used to resolve to here. */
    background: var(--gp-color-fill-ink);
    color: #fff;
}
/* Add Video Button */
.gp-add-video-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 12px 20px;
    background: var(--gp-accent-gold);
    color: #000;
    border: none;
    border-radius: var(--gp-card-radius);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.2s ease, transform 0.1s ease;
    font-family: inherit;
    white-space: nowrap;
    box-shadow: var(--gp-card-shadow);
}
.gp-add-video-btn:hover {
    background: var(--gp-accent-gold-hover);
}
.gp-add-video-btn:active {
    transform: scale(var(--gp-press-scale-button)); /* F2 (2026-07-26): converged onto the shared token, was a local 0.98 */
}
/* Card Header with Inline Filters */
.gp-card-header-with-filters {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--gp-border-color);
    flex-wrap: wrap;
}
.gp-card-header-with-filters .gp-filter-buttons {
    display: flex;
    gap: 4px;
    flex: 1;
    max-width: 500px;
    background: var(--gp-bg-gray);
    border-radius: var(--gp-card-radius);
    padding: 4px;
}
.gp-card-header-with-filters .gp-filter-btn {
    padding: 8px 12px;
    font-size: 13px;
}
.gp-card-header-with-filters .gp-add-video-btn {
    padding: 8px 16px;
    font-size: 13px;
}
/* No Filter Results Message */
.gp-no-filter-results {
    text-align: center;
    padding: 40px 20px;
    color: var(--gp-text-secondary);
    font-size: 15px;
}
.gp-no-filter-results svg {
    width: 48px;
    height: 48px;
    stroke: #ccc;
    margin-bottom: 12px;
    display: block;
    margin-left: auto;
    margin-right: auto;
}
/* Modal Meta Items */
.gp-video-modal-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 20px;
    margin: 12px 0;
    font-size: 14px;
    color: var(--gp-text-secondary);
}
.gp-modal-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.gp-modal-meta-item strong {
    color: var(--gp-text-primary);
    font-weight: 600;
}
/* ========================================
   ABOUT TAB CONTENT
   ======================================== */
.gp-intro-video iframe {
    width: 100%;
    height: 400px;
    border-radius: 8px;
    border: none;
}
.gp-bio-text {
    font-size: 16px;
    line-height: 1.7;
    color: var(--gp-text-primary);
}
.gp-info-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
}
.gp-info-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px;
    background: var(--gp-bg-gray);
    border-radius: 8px;
}
.gp-info-icon {
    width: 40px;
    height: 40px;
    background: #1a1a1a;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.gp-info-icon svg {
    width: 20px;
    height: 20px;
    stroke: var(--gp-accent-gold);
}
.gp-info-text {
    flex: 1;
    min-width: 0;
}
.gp-info-label {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--gp-text-secondary);
    margin-bottom: 2px;
    font-weight: 500;
}
.gp-info-value {
    font-size: 15px;
    font-weight: 600;
    color: var(--gp-text-primary);
    word-break: break-word;
}
.gp-info-value a {
    color: var(--gp-link);
    text-decoration: none;
}
.gp-info-value a:hover {
    text-decoration: underline;
}
.gp-info-subvalue {
    font-size: 13px;
    font-weight: 400;
    color: var(--gp-text-secondary);
    margin-top: 2px;
}
/* Support Team Section */
.gp-support-team-section {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid var(--gp-border-color);
}
.gp-section-subtitle {
    font-size: 14px;
    font-weight: 600;
    color: var(--gp-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin: 0 0 16px 0;
}
/* Contact Toggle */
.gp-contact-toggle {
    width: 100%;
    padding: 12px 20px;
    background: var(--gp-bg-gray);
    border: none;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 600;
    color: var(--gp-text-primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: background-color 0.2s ease;
    font-family: inherit;
}
.gp-contact-toggle:hover {
    background: #d8dadf;
}
.gp-contact-toggle svg {
    transition: transform 0.2s ease;
}
.gp-contact-toggle.open svg {
    transform: rotate(180deg);
}
.gp-contact-content {
    display: none;
    margin-top: 16px;
}
.gp-contact-content.show {
    display: block;
}
/* ========================================
   VIDEO GRID & EVENT CARDS
   ======================================== */
.gp-event-cards {
    display: flex;
    flex-direction: column;
    gap: var(--gp-card-gap);
}
.gp-video-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
}
.gp-no-videos {
    text-align: center;
    padding: 40px 20px;
    color: var(--gp-text-secondary);
    font-size: 15px;
}
.gp-no-videos svg {
    width: 48px;
    height: 48px;
    stroke: #ccc;
    margin-bottom: 12px;
}
/* ========================================
   VIDEO CARDS - Scout Directory Style
   Added: 2025-12-28
   
   Thumbnail background with play button overlay,
   event + type badges, score badge, click-to-modal
   ======================================== */
/* Video Card Container */
.gp-video-card {
    background: var(--gp-card-bg);
    border-radius: var(--gp-card-radius);
    box-shadow: var(--gp-card-shadow);
    overflow: hidden;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    cursor: pointer;
    display: flex;
    flex-direction: column;
}
.gp-video-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
/* Intro video card - thumbnail only, no extra space */
.gp-intro-video-card {
    background: transparent;
    box-shadow: none;
    border-radius: 0 0 12px 12px;
}
.gp-intro-video-card .gp-video-card-thumbnail {
    border-radius: 0 0 12px 12px;
    overflow: hidden;
    aspect-ratio: 16 / 9;       /* keep the intro card uniform 16:9 like the others */
    background-color: #000;     /* black pillarbox bars for portrait intros */
}
.gp-intro-video-card .gp-video-card-thumbnail img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;        /* show the whole intro (pillarbox), never crop a face */
}
/* Thumbnail with background image */
.gp-video-card-thumbnail {
    position: relative;
    aspect-ratio: 16 / 9;
    background-color: #1a1a1a;
    background-size: cover;
    background-position: center;
    flex-shrink: 0;
}
/* Self-hosted/direct-file videos have no platform poster; render a frame from the
   video itself behind the play button + badges. Non-interactive so the card's own
   click-to-play still fires. (iOS/Safari may not paint the frame — falls back to
   the dark background, same as before.) */
.gp-video-card-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    pointer-events: none;
    background-color: #1a1a1a;
}
/* Play button overlay - centered, gold accent */
.gp-video-play-overlay {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 56px;
    height: 56px;
    background: var(--gp-accent-gold);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0.9;
    transition: transform 0.2s ease, opacity 0.2s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    z-index: 5;
}
.gp-video-play-overlay svg {
    width: 24px;
    height: 24px;
    color: #000;
    margin-left: 3px; /* Visual centering for play icon */
}
.gp-video-card:hover .gp-video-play-overlay {
    transform: translate(-50%, -50%) scale(1.1);
    opacity: 1;
}
/* Badges container - top left */
.gp-video-card-badges {
    position: absolute;
    top: 10px;
    left: 10px;
    display: flex;
    gap: 6px;
    z-index: 2;
}
/* Individual badge */
.gp-video-badge {
    padding: 4px 10px;
    background: rgba(0, 0, 0, 0.75);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    border-radius: 4px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    backdrop-filter: blur(4px);
}
.gp-video-badge.gold {
    background: var(--gp-accent-gold);
    color: #000;
}
/* Pinned ("featured") badge — reuses the frosted .gp-video-badge base (dark blur +
   white text, legible over any thumbnail); the pushpin icon + label mark featured
   status to everyone. */
.gp-video-badge--pinned {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    padding: 4px; /* icon-only: square chip, height matches the sibling event/type badges */
}
.gp-video-badge--pinned svg {
    flex-shrink: 0;
    display: block;
}
/* Featured cards: a subtle neutral ring (dark-aware token) over the standard card
   shadow so the (top-sorted) pinned ones read as a set. No accent colour — gold stays
   brand-only; the ring is the signal, the badge + top-sort do the rest. */
.gp-video-card.is-pinned {
    box-shadow: 0 0 0 1.5px var(--gp-color-border-strong), var(--gp-card-shadow);
}
/* Score badge - top right */
.gp-video-score-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    padding: 6px 12px;
    background: var(--gp-accent-gold);
    color: #000;
    font-size: 15px;
    font-weight: 700;
    border-radius: 6px;
    font-family: 'Poppins', sans-serif;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    z-index: 2;
}
/* Edit/Delete menu - positioned on thumbnail, bottom right */
.gp-video-menu {
    position: absolute;
    bottom: 10px;
    right: 10px;
    z-index: 10; /* Above play overlay (z-index: 5) so clicks reach menu first */
}
.gp-video-menu-btn {
    width: 36px;
    height: 36px;
    background: rgba(0, 0, 0, 0.6) !important;
    border: none;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s ease, background-color 0.2s ease;
    color: #fff;
    font-size: 18px;
}
.gp-video-card:hover .gp-video-menu-btn {
    opacity: 1;
}
.gp-video-menu-btn:hover {
    background: rgba(0, 0, 0, 0.8) !important;
    color: #fff;
}
/* Dropdown menu */
.gp-video-menu-dropdown {
    position: absolute;
    bottom: 100%;
    right: 0;
    margin-bottom: 4px;
    background: var(--gp-card-bg);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
    min-width: 140px;
    overflow: hidden;
    display: none;
    z-index: 100;
}
/* Single source of truth for dropdown visibility: the JS toggles .active on the
   dropdown itself (handleVideoMenus). Hover-open and the container-.active rule
   were removed — they conflicted with the click toggle and left menus stuck open. */
.gp-video-menu-dropdown.active {
    display: block;
}
.gp-video-menu-dropdown button {
    width: 100%;
    padding: 10px 14px;
    background: none;
    border: none;
    font-size: 13px;
    font-weight: 500;
    color: var(--gp-text-primary) !important;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    text-align: left;
    font-family: inherit;
    transition: background-color 0.2s ease;
}
.gp-video-menu-dropdown button:hover {
    background: var(--gp-bg-gray);
    color: #1c1e21 !important;
}
.gp-video-menu-dropdown .gp-video-edit-btn {
    color: #1c1e21 !important;
}
.gp-video-menu-dropdown .gp-video-edit-btn:hover {
    background: var(--gp-bg-gray);
    color: #6b7280 !important;
}
.gp-video-menu-dropdown .gp-video-delete-btn {
    color: var(--gp-danger) !important;
}
.gp-video-menu-dropdown .gp-video-delete-btn:hover {
    background: rgba(231, 76, 60, 0.1);
    color: var(--gp-danger) !important;
}
/* Ensure SVG icons in dropdown have correct colors */
.gp-video-menu-dropdown .gp-video-edit-btn svg {
    stroke: #1c1e21 !important;
    transition: stroke 0.2s ease;
}
.gp-video-menu-dropdown .gp-video-edit-btn:hover svg {
    stroke: #6b7280 !important;
}
.gp-video-menu-dropdown .gp-video-delete-btn svg {
    stroke: var(--gp-danger) !important;
}
/* Pin/Unpin item inherits the dropdown button layout + colour; just keep its icon firm. */
.gp-video-menu-dropdown .gp-video-pin-btn svg {
    flex-shrink: 0;
}
/* Card body */
.gp-video-card-body {
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    flex: 1;
}
.gp-video-card-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--gp-text-primary);
    margin: 0 0 6px 0;
    line-height: 1.3;
    /* Limit to 2 lines */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.gp-video-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 12px;
    font-size: 13px;
    color: var(--gp-text-secondary);
}
.gp-video-meta-item {
    display: inline-flex;
    align-items: center;
}
.gp-video-meta-item.gp-video-letter {
    font-weight: 600;
    color: var(--gp-accent-gold-text); /* R0: 13px meta text on the white video card */
}
/* Video Card Details - Structured layout for Routines & Skills */
.gp-video-card-details {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 13px;
    color: var(--gp-text-secondary);
}
.gp-video-detail-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.gp-video-detail-row svg {
    flex-shrink: 0;
    opacity: 0.7;
}
.gp-video-detail-label {
    font-weight: 500;
    color: var(--gp-text-secondary);
    min-width: 65px;
    flex-shrink: 0;
}
.gp-video-detail-value {
    color: var(--gp-text-primary);
    font-weight: 500;
}
/* Competition row with icon */
.gp-video-competition {
    color: var(--gp-text-primary);
    font-weight: 500;
}
.gp-video-competition svg {
    color: var(--gp-accent-gold);
    opacity: 1;
}
/* Video description (truncated) */
.gp-video-description {
    font-size: 12px;
    line-height: 1.4;
    color: var(--gp-text-secondary);
    margin: 4px 0;
    /* Limit to 2 lines */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* Date row */
.gp-video-date {
    margin-top: auto;
    padding-top: 6px;
    font-size: 12px;
}
.gp-video-date svg {
    color: var(--gp-text-secondary);
}
/* Legacy video item styles (for backwards compatibility) */
.gp-video-item {
    background: var(--gp-bg-gray);
    border-radius: 12px;
    overflow: hidden;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    will-change: transform;
}
.gp-video-item:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
.gp-video-thumbnail {
    position: relative;
    aspect-ratio: 16 / 9;
    background: #000;
}
.gp-video-thumbnail iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: none;
}
.gp-video-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
}
.gp-video-placeholder svg {
    stroke: rgba(255, 255, 255, 0.3);
}
.gp-video-info {
    padding: 12px 14px;
}
.gp-video-title {
    font-size: 15px;
    font-weight: 600;
    margin: 0 0 6px 0;
    color: var(--gp-text-primary);
}
.gp-video-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 13px;
    color: var(--gp-text-secondary);
}
.gp-video-meta span {
    display: inline-flex;
    align-items: center;
}
.gp-video-notes {
    font-size: 13px;
    color: var(--gp-text-secondary);
    margin-top: 8px;
    line-height: 1.4;
}
/* ========================================
   VIDEO PLAYBACK MODAL
   ======================================== */
.gp-video-modal {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.92);
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 40px;
}
.gp-video-modal.active {
    display: flex;
    animation: gpOverlayIn 0.2s ease-out;
}
@keyframes gpOverlayIn {
    from { opacity: 0; }
    to { opacity: 1; }
}
/* Width is capped so that 16:9 video + ~48px header + ~150px info + 80px padding never exceeds viewport */
.gp-video-modal-content {
    position: relative;
    width: 100%;
    max-width: min(960px, calc((100vh - 278px) * 16 / 9));
    background: #1a1a1a;
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.08);
    animation: gpModalIn 0.25s ease-out;
}
@keyframes gpModalIn {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}
/* Close button styles are in single-gymnast_profile.php inline styles */
/* Video player - 16:9 aspect ratio, never overflows because modal width is pre-constrained */
.gp-video-modal-player {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    overflow: hidden;
}
/* Wrapper created by JS - fills the player area completely */
.gp-video-modal-player .gp-video-player-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
/* iframe/video fills the wrapper */
.gp-video-modal-player iframe,
.gp-video-modal-player video {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: none;
}
/* Modal info section */
.gp-video-modal-info {
    padding: 20px 24px;
    overflow-y: auto;
    flex-shrink: 0;
    background: #1a1a1a;
}
.gp-video-modal-title {
    font-size: 18px;
    font-weight: 700;
    color: #fff;
    margin: 0 0 12px 0;
}
.gp-video-modal-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 16px;
}
.gp-video-modal-meta-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.gp-video-modal-meta-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: rgba(255, 255, 255, 0.5);
}
.gp-video-modal-meta-value {
    font-size: 15px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.9);
}
.gp-video-modal-meta-value.gold {
    color: var(--gp-accent-gold);
}
.gp-video-modal-description {
    font-size: 14px;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.6);
    margin: 0;
    padding-top: 12px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}
/* ========================================
   PROFILE URL (custom slug row in Edit Profile)
   ======================================== */
.gp-profile-url-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* The fixed domain prefix reads as context, not as an input: its own line so
   the row never overflows at phone widths. */
.gp-profile-url-prefix {
    flex-basis: 100%;
    color: var(--gp-text-secondary);
    font-size: 13px;
    word-break: break-all;
}

.gp-profile-url-row .gp-form-input {
    flex: 1;
    min-width: 0;
}

.gp-profile-url-row .gp-btn-secondary {
    flex-shrink: 0;
}

/* ========================================
   MODAL SYSTEM (Edit/Add Modals)
   Scoped :not(.gp-surface): the shared More sheet is a
   <dialog class="gp-more-sheet gp-modal-overlay gp-surface"> with an inner
   .gp-modal (inc/gp-mobile-nav-system.php), so bare .gp-modal-overlay /
   .gp-modal rules here land on it and fight css/gp-surface.css (frozen).
   That fight was the sheet's double open animation: this file's center-anchor
   + scale transition ran on top of the surface slide-up. These rules are for
   the profile's OWN modals only; anything carrying .gp-surface is excluded.
   ======================================== */
.gp-modal-overlay:not(.gp-surface) {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(4px);
    z-index: 10000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 20px;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.gp-modal-overlay.active {
    display: flex;
    opacity: 1;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal {
    background: var(--gp-card-bg);
    border-radius: 16px;
    width: 100%;
    max-width: 560px;
    max-height: 90vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    transform: scale(0.95);
    transition: transform 0.2s ease;
}
.gp-modal-large {
    max-width: 720px;
}
.gp-modal-overlay.active .gp-modal {
    transform: scale(1);
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    border-bottom: 1px solid var(--gp-border-color);
    flex-shrink: 0;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-title { /* heading ramp: h5 */
    font-size: var(--gp-h5-size);
    line-height: var(--gp-h5-line);
    font-weight: var(--gp-h5-weight);
    letter-spacing: var(--gp-h5-tracking);
    color: var(--gp-text-primary);
    margin: 0;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-close {
    width: 36px;
    height: 36px;
    border-radius: 0;
    border: none;
    background: transparent;
    color: #000;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.2s ease;
    flex-shrink: 0;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-close svg {
    width: 24px;
    height: 24px;
    stroke: #000 !important;
    stroke-width: 2px;
    display: block;
}
/* Dark-mode readability (UB, 2026-07-25 wave 3) — the close (X) icon was hardcoded
   black (color + an !important stroke), so on the dark modal panel it disappeared
   entirely instead of just being low-contrast. Light is untouched. */
[data-theme="dark"] .gp-modal-overlay:not(.gp-surface) .gp-modal-close {
    color: var(--gp-color-text);
}
[data-theme="dark"] .gp-modal-overlay:not(.gp-surface) .gp-modal-close svg {
    stroke: var(--gp-color-text) !important;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-close:hover {
    opacity: 0.6;
}
/* ========================================
   MODAL TABS (Profile / Support Team)
   ======================================== */
.gp-modal-overlay:not(.gp-surface) .gp-modal-tabs {
    display: flex;
    gap: 0;
    padding: 0 24px;
    border-bottom: 1px solid var(--gp-border-color);
    background: var(--gp-card-bg); /* D2 sweep: was raw fff (white), matches the surrounding rule's own var(--gp-border-color)/var(--gp-text-*) usage */
    flex-shrink: 0;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-tab {
    padding: 14px 24px;
    border: none;
    background: transparent;
    font-size: 14px;
    font-weight: 600;
    color: var(--gp-text-secondary);
    cursor: pointer;
    position: relative;
    transition: color 0.2s ease;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-tab:hover {
    color: var(--gp-text-primary);
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-tab.active {
    color: var(--gp-accent-gold-text); /* R0: the active tab LABEL on the white modal header. The 3px underline bar below keeps the fill gold */
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-tab.active::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--gp-accent-gold);
    border-radius: 3px 3px 0 0;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-tab-content {
    display: none;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-tab-content.active {
    display: block;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-body {
    padding: 24px;
    overflow-y: auto;
    flex: 1;
    -webkit-overflow-scrolling: touch;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    padding: 16px 24px;
    border-top: 1px solid var(--gp-border-color);
    background: var(--gp-bg-gray);
    flex-shrink: 0;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-footer .gp-btn {
    background: #1a1a2e;
    color: #fff;
}
.gp-modal-overlay:not(.gp-surface) .gp-modal-footer .gp-btn:hover {
    background: #2d2d44;
}
/* ========================================
   MODAL SYSTEM — DESKTOP CHROME FOR SURFACE DIALOGS (>= 1025px)
   ----------------------------------------------------------------
   Companion to the :not(.gp-surface) block above, and the other half of the
   contract css/gp-surface.css states in its own header: "The legacy class still
   drives the DESKTOP look; the rules below take over on mobile."

   gp-surface.css dresses a <dialog class="gp-modal-overlay gp-surface"> ONLY
   inside @media (max-width: 1024px). Scoping the base block off .gp-surface
   (2f156d2) was right for mobile, where the frozen surface pattern owns the
   presentation, but it left the profile's own surface dialogs
   (#editProfileModal, #addVideoModal) matching NEITHER ruleset from 1025px up:
   a bare UA <dialog> — opaque white, no card, no header rule, no dim, and
   overflow:visible with no scroller, so the lower two thirds of the form was
   unreachable.

   This block restores exactly that missing desktop chrome. It is deliberately
   ADDITIVE and width-gated: nothing here reaches <= 1024px, so the More sheet's
   single clean slide-up (the bug 2f156d2 fixed) is untouched by construction.
   Keep the two blocks in sync; the declarations mirror the base block above,
   with the two hardcoded inks re-pointed at Tier-2 tokens so dark mode follows
   without a separate override.

   WHY EVERY SELECTOR HERE IS WRAPPED IN :where()
   This block does not only reach the profile's own two dialogs. Anything on the
   page carrying .gp-modal-overlay.gp-surface matches, and gp-profile.css also
   loads under the video-likes sheet and (on the app door) the More sheet. Those
   FEATURE sheets already own their desktop presentation through their own class
   at (0,2,0) — see .gp-more-sheet in css/gp-mobile-core.css, which documents its
   values as "the base the sheet falls back to at 1025px and up". :where()
   contributes zero specificity, so each rule below lands at exactly the weight
   its pre-2f156d2 counterpart had (.gp-modal-overlay and .gp-modal were both
   (0,1,0)) and every feature sheet keeps winning, as it did before the
   regression. Written at the natural (0,2,0)/(0,3,0) weight instead, this block
   silently re-widths feature sheets: measured on the app door at 1440x900, the
   since-retired theme picker went 420px -> 560px and the More sheet
   100% -> 560px. Do not unwrap them.
   ======================================== */
@media (min-width: 1025px) {
    .gp-modal-overlay:where(.gp-surface) {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.6);
        backdrop-filter: blur(4px);
        z-index: 10000;
        align-items: center;
        justify-content: center;
        padding: 20px;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal {
        background: var(--gp-card-bg);
        border-radius: 16px;
        width: 100%;
        max-width: 560px;
        max-height: 90vh;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    }
    /* The panel rule above is (0,1,0), the same weight as the bare
       .gp-modal-large declared earlier in this file, and it comes later, so it
       wins the tie and would narrow the wide Edit Profile panel to 560px.
       Restate the variant here, after it.

       PROPORTIONS (owner, 2026-08-15): "a little bit more square." At 720px wide
       and free to grow to 90vh, the Edit Profile panel was a tall narrow column
       — 720x810 at 1440x900 and 720x972 at 1920x1080, i.e. taller than it is
       wide, so a two-column form read as a deep well.

       Two numbers fix the shape, and both are chosen for the SMALL desktop, not
       the big one:
       - 960px wide. The binding case is 1280: the overlay's own 20px padding
         leaves 1240px, so 960 still clears a 160px scrim either side and never
         touches the edge. It is a real step up from 720 (the .gp-form-row
         two-column grid goes from ~336px to ~456px per column) without becoming
         a full-bleed slab on a 1920 monitor, where it sits at half the width.
       - max-height caps at 760px as well as 90vh. 90vh ALONE keeps the dialog
         on screen (that is the guarantee below) but lets a tall monitor stretch
         it back into a column: 90vh is 972px at 1080. Taking the smaller of the
         two holds the panel at roughly 4:3 everywhere — 960x720 at 800 tall,
         960x760 at 900 and 1080 — so the dialog is the same shape on every
         desktop instead of growing a new one per monitor.

       The height is a CAP, not a size: .gp-modal is a flex column whose header,
       tab row and footer are all flex-shrink:0 and whose .gp-modal-body is
       flex:1 with overflow-y:auto, so the extra form length goes into the body's
       own scroller and the footer with Save Changes stays on screen. That is the
       second half of the owner's ask ("i need to make it show in the picture")
       and tests/system/journey-profile-modal-proportions.mjs measures the footer
       rect against the viewport at 1280x800, 1440x900 and 1920x1080.

       .gp-modal-large is used in exactly ONE place in the theme (the Edit
       Profile panel, page-templates/single-gymnast_profile.php:1506), so this
       reshapes nothing else. #addVideoModal and #gpVideoLikesSheet keep the
       560px default from the rule above, untouched. */
    :where(.gp-modal-overlay.gp-surface) .gp-modal-large {
        max-width: 960px;
        max-height: min(90vh, 760px);
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 20px 24px;
        border-bottom: 1px solid var(--gp-border-color);
        flex-shrink: 0;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-title { /* heading ramp: h5 */
        font-size: var(--gp-h5-size);
        line-height: var(--gp-h5-line);
        font-weight: var(--gp-h5-weight);
        letter-spacing: var(--gp-h5-tracking);
        color: var(--gp-text-primary);
        margin: 0;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-close {
        width: 36px;
        height: 36px;
        border-radius: 0;
        border: none;
        background: transparent;
        color: var(--gp-color-icon-ink);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: opacity 0.2s ease;
        flex-shrink: 0;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-close svg {
        width: 24px;
        height: 24px;
        stroke: currentColor;
        stroke-width: 2px;
        display: block;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-close:hover {
        opacity: 0.6;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tabs {
        display: flex;
        gap: 0;
        padding: 0 24px;
        border-bottom: 1px solid var(--gp-border-color);
        background: var(--gp-card-bg);
        flex-shrink: 0;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tab {
        padding: 14px 24px;
        border: none;
        background: transparent;
        font-size: 14px;
        font-weight: 600;
        color: var(--gp-text-secondary);
        cursor: pointer;
        position: relative;
        transition: color 0.2s ease;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tab:hover {
        color: var(--gp-text-primary);
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tab.active {
        color: var(--gp-accent-gold-text);
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tab.active::after {
        content: '';
        position: absolute;
        bottom: -1px;
        left: 0;
        right: 0;
        height: 3px;
        background: var(--gp-accent-gold);
        border-radius: 3px 3px 0 0;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tab-content {
        display: none;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-tab-content.active {
        display: block;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-body {
        padding: 24px;
        overflow-y: auto;
        flex: 1;
        -webkit-overflow-scrolling: touch;
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-footer {
        display: flex;
        justify-content: flex-end;
        gap: 12px;
        padding: 16px 24px;
        border-top: 1px solid var(--gp-border-color);
        background: var(--gp-bg-gray);
        flex-shrink: 0;
    }
    /* THE PRIMARY ACTION IS INK-FILLED AT DESKTOP (owner, 2026-08-15)
       "Save Changes: black background, white text, like the College Tracker
       button." That button is #addModal / #detailsPanel .gp-btn-save in
       css/gp-college-tracker.css (~2096 and ~2182) — ungated, so it is what the
       owner sees at desktop — and it is already tokenized:
           background: var(--gp-color-btn-ink-bg);       (light #111827)
           color:      var(--gp-color-on-primary);
           :hover      var(--gp-color-btn-ink-bg-hover); (light #000)
       Consuming the SAME Tier-2 pair rather than restating the values is the
       point of the request: the two buttons now cannot drift, and a retune of
       the token moves both.

       ON DEVIATING FROM GOLD. CLAUDE.md makes gold the CTA/accent intent, and
       the base .gp-btn-save (~line 578, all widths) is gold-on-black. This is a
       deliberate desktop-only exception on the owner's explicit instruction, and
       it is spent on an existing semantic — no new token, no Tier-1 primitive,
       no raw hex. Worth noting it also repairs a real contrast problem: gold
       sits on the footer's own var(--gp-bg-gray) at 1.68:1, so the primary
       action barely separated from the bar it sits on. The ink fill takes that
       to ~15:1.

       DARK MODE IS ANSWERED BY THE TOKEN, NOT BY AN OVERRIDE. The failure to
       fear here is a black button disappearing into a dark panel. It cannot
       happen: --gp-color-btn-ink-bg is redefined to var(--gp-gold) under
       [data-theme="dark"] (assets/css/gp-base.css:625), the app's existing
       "primary action goes gold in dark" convention, with --gp-color-on-primary
       supplying the dark ink to sit on it. So dark mode keeps exactly the gold
       button it has today, and only LIGHT mode changes. Measured in the journey.

       SCOPE. This is (0,2,0) inside the width gate, beating the (0,1,0) base
       rule from 1025px up and reaching nothing below it, so the mobile cover
       keeps its gold Save untouched. It intentionally also dresses
       #addVideoModal's "Add Video" button, the only other .gp-surface dialog on
       this page with a footer action: two adjacent dialogs on one page with
       differently coloured primary buttons would read as a bug, not a choice.
       The Delete confirm modal is a plain <div class="gp-modal-overlay"> with no
       .gp-surface, so its red button is out of scope and unchanged. */
    :where(.gp-modal-overlay.gp-surface) .gp-modal-footer .gp-btn-save {
        background: var(--gp-color-btn-ink-bg);
        color: var(--gp-color-on-primary);
    }
    :where(.gp-modal-overlay.gp-surface) .gp-modal-footer .gp-btn-save:hover {
        background: var(--gp-color-btn-ink-bg-hover);
    }
}
/* ========================================
   FORM STYLES
   ======================================== */
.gp-form-section {
    margin-bottom: 24px;
}
.gp-form-section:last-child {
    margin-bottom: 0;
}
.gp-form-section-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--gp-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--gp-border-color);
}
.gp-form-group {
    margin-bottom: 16px;
}
.gp-form-group:last-child {
    margin-bottom: 0;
}
.gp-form-label {
    display: block;
    font-size: 14px;
    font-weight: 600;
    color: var(--gp-text-primary);
    margin-bottom: 6px;
}
.gp-form-label .required {
    color: var(--gp-danger);
}
.gp-form-input,
.gp-form-select,
.gp-form-textarea {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--gp-border-color);
    border-radius: 8px;
    font-size: 15px;
    font-family: inherit;
    background: var(--gp-card-bg); /* D2 sweep: was raw fff (white), matches the surrounding rule's own var(--gp-border-color) usage */
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.gp-form-input:focus,
.gp-form-select:focus,
.gp-form-textarea:focus {
    outline: none;
    border-color: var(--gp-accent-gold);
    box-shadow: 0 0 0 3px rgba(223, 184, 89, 0.2);
}
/* Read-only field indicator (email, in the Edit Profile modal) — was a raw
   inline style="" attribute setting a light-gray background (an inline style
   wins the cascade over any stylesheet rule, so there was no way to
   dark-override it in place); pulled into a class so dark mode can target
   it. Byte-identical to the old inline declaration in light (same Tier-1
   value, referenced through the token instead of a literal). */
.gp-form-input--readonly {
    background: var(--gp-gray-100);
    cursor: not-allowed;
}
[data-theme="dark"] .gp-form-input--readonly {
    background: var(--gp-color-surface-2);
}
.gp-form-textarea {
    min-height: 100px;
    resize: vertical;
}
/* AUTO-GROWING TEXTAREA (opt-in via data-gp-autogrow; today only Bio / About Me)
   The field's height is written by initAutoGrowFields() in js/gp-profile.js, so
   all this rule does is remove the two things that would fight it:
   - overflow-y: hidden. Once the box is as tall as its text there is nothing to
     scroll, and leaving it on `auto` makes Chrome reserve a scrollbar gutter
     while the height is being recomputed, which shows as a one-frame flicker on
     every keystroke.
   - resize: none. A drag handle sets an inline height that the very next
     keystroke overwrites, so the control would appear broken. The field is
     always exactly as tall as its content, which is what the handle was for.
   min-height still comes from the rules above (and from the 768px block further
   down), so an empty bio keeps its floor instead of collapsing to one line.
   No max-height: the ask is "show all of the text", and maxlength=500 on the
   input is what bounds how tall this can ever get. */
.gp-form-textarea[data-gp-autogrow] {
    overflow-y: hidden;
    resize: none;
}
.gp-form-hint {
    font-size: 12px;
    color: var(--gp-text-secondary);
    margin-top: 4px;
}
.gp-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}
.gp-form-checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
}
.gp-form-checkbox input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--gp-accent-gold);
    cursor: pointer;
}
/* Radio Buttons */
.gp-form-radio-group {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.gp-form-radio {
    position: relative;
}
.gp-form-radio input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.gp-form-radio label {
    display: block;
    padding: 10px 16px;
    background: var(--gp-bg-gray);
    border: 2px solid transparent;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}
.gp-form-radio input:checked + label {
    background: var(--gp-color-surface-3);
    border-color: var(--gp-accent-gold);
    color: var(--gp-text-primary);
}
.gp-form-radio label:hover {
    background: #e4e6eb;
}
/* Photo Upload */
.gp-photo-upload {
    display: flex;
    gap: 20px;
    align-items: center;
}
.gp-photo-preview {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: #d3d3d3; /* Gray background for transparent PNG corners */
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--gp-border-color);
    flex-shrink: 0;
    position: relative; /* anchor for .gp-upload-overlay */
}
.gp-photo-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.gp-photo-preview svg {
    width: 32px;
    height: 32px;
    stroke: #ccc;
}
/* Video Preview */
.gp-video-preview {
    margin-top: 12px;
    border-radius: 8px;
    overflow: hidden;
    background: #000;
}
/* ========================================
   TOAST NOTIFICATIONS
   ======================================== */
.gp-toast-container {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 10001;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.gp-toast {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 20px;
    background: #333;
    color: #fff;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 500;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    animation: gpSlideIn 0.3s ease;
}
.gp-toast.success {
    background: var(--gp-success);
}
.gp-toast.error {
    background: var(--gp-danger);
}
@keyframes gpSlideIn {
    from {
        transform: translateX(100%);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}
/* Loading Spinner */
.gp-spinner {
    width: 16px;
    height: 16px;
    border: 2px solid transparent;
    border-top-color: currentColor;
    border-radius: 50%;
    animation: gpSpin 0.8s linear infinite;
    display: inline-block;
}
@keyframes gpSpin {
    to { transform: rotate(360deg); }
}
/* ========================================
   DELETE CONFIRMATION MODAL
   ======================================== */
.gp-delete-warning {
    text-align: center;
    padding: 20px 0;
}
.gp-delete-icon {
    width: 64px;
    height: 64px;
    background: rgba(231, 76, 60, 0.1);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 16px;
}
.gp-delete-icon svg {
    width: 32px;
    height: 32px;
    stroke: var(--gp-danger);
}
.gp-delete-warning p {
    color: var(--gp-text-secondary);
    margin: 0;
}
.gp-delete-warning strong {
    color: var(--gp-text-primary);
}
/* ========================================
   MOBILE RESPONSIVE - COMPREHENSIVE
   Updated: 2026-01-16
   ======================================== */

/* -----------------------------------------
   TABLET BREAKPOINT (769px - 1024px)
   ----------------------------------------- */
@media (max-width: 1024px) and (min-width: 769px) {
    .gp-profile-wrapper {
        max-width: 100%;
        padding: 16px;
    }
    
    .gp-header-content {
        padding: 24px 20px 24px 20px;
    }
    
    .gp-profile-photo {
        width: 176px;
        height: 176px;
    }
    
    .gp-video-grid {
        grid-template-columns: 1fr;
        gap: 16px;
    }
}

/* -----------------------------------------
   TABLET BREAKPOINT (1024px and below)
   Applies to: Landscape phones, tablets
   Centered layout with constrained widths
   ----------------------------------------- */
@media (max-width: 1024px) {
    /* ----- Profile Wrapper - Constrain width ----- */
    .gp-profile-wrapper {
        max-width: 100%;
        margin: 0 auto;
        padding-left: var(--gp-space-md);
        padding-right: var(--gp-space-md);
    }
    
    /* ----- Profile Header - Centered layout ----- */
    .gp-profile-header {
        max-width: var(--gp-content-max);
        margin-left: auto;
        margin-right: auto;
        border-radius: var(--gp-card-radius);
        overflow: hidden;
    }
    
    .gp-header-content {
        flex-direction: column;
        align-items: center;
        text-align: center;
        padding: 0 var(--gp-space-md) var(--gp-space-lg);
        gap: var(--gp-space-md);
    }
    
    .gp-profile-info {
        width: 100%;
        max-width: var(--gp-content-max);
    }
    
    .gp-name-row {
        justify-content: center;
        flex-wrap: wrap;
    }
    
    .gp-profile-meta {
        justify-content: center;
    }
    
    .gp-events-badges {
        justify-content: center;
    }
    
    /* ----- Profile Actions - Constrained buttons ----- */
    .gp-profile-actions {
        justify-content: center;
        width: 100%;
        max-width: var(--gp-content-max);
        margin: 0 auto;
        gap: var(--gp-space-sm);
    }
    
    .gp-profile-actions .gp-btn,
    .gp-profile-actions .gp-btn-star {
        flex: 0 1 auto;
        width: auto;
        min-width: 140px;
        max-width: var(--gp-btn-max);
        justify-content: center;
    }
    
    /* ----- Tab Navigation - Centered ----- */
    .gp-tab-navigation {
        max-width: var(--gp-content-max);
        margin-left: auto;
        margin-right: auto;
        border-radius: var(--gp-card-radius);
    }
    
    /* ----- Tab Content - Constrained ----- */
    .gp-tab-content {
        max-width: var(--gp-content-max);
        margin-left: auto;
        margin-right: auto;
    }
    
    /* ----- Cards - Constrained ----- */
    :where(.gp-profile-wrapper) .gp-card {
        max-width: var(--gp-content-max);
        margin-left: auto;
        margin-right: auto;
    }
    
    /* ----- Add Video Button - Constrained ----- */
    .gp-add-video-btn {
        max-width: var(--gp-btn-max);
        margin-left: auto;
        margin-right: auto;
        display: block;
    }
    
    /* ----- Video Grid ----- */
    .gp-video-grid {
        max-width: var(--gp-content-max);
        margin-left: auto;
        margin-right: auto;
        grid-template-columns: 1fr;
        gap: 16px;
    }
    
    /* ----- Filter Buttons - Centered ----- */
    .gp-filter-buttons {
        justify-content: center;
        max-width: var(--gp-content-max);
        margin-left: auto;
        margin-right: auto;
    }
}

/* -----------------------------------------
   MOBILE BREAKPOINT (768px and below)
   Portrait phones - additional refinements
   ----------------------------------------- */
@media (max-width: 768px) {
    /* ----- Profile Wrapper ----- */
    .gp-profile-wrapper {
        padding: 0 0 24px 0;
        margin-top: 0;
        /* Clear space for the fixed mobile header + safe area + breathing room.
           The header's real height is the token (52px since the G1 shell
           geometry); the old 56px literal painted a 4px gap strip under it. */
        padding-top: calc(var(--gp-mobile-header-height, 52px) + env(safe-area-inset-top, 0px) + 12px) !important;
        background: var(--gp-bg-gray);
    }
    
    /* Ensure profile header card doesn't have negative margins that pull it under the mobile nav */
    .gp-profile-header {
        margin-top: 0;
        border-radius: 0;
        margin-bottom: 12px;
        max-width: 100%;
    }
    
    .gp-cover-photo {
        height: 140px;
    }
    
    .gp-header-content {
        flex-direction: column;
        align-items: center;
        text-align: center;
        padding: 0 16px 20px 16px;
        margin-top: -50px;
        gap: 12px;
    }
    
    .gp-profile-header:not(.has-cover) .gp-header-content {
        padding-top: 20px;
        margin-top: 0;
    }
    
    .gp-profile-photo {
        width: 196px;
        height: 196px;
        border-width: 3px;
    }
    
    .gp-profile-photo-placeholder {
        font-size: 40px;
    }
    
    .gp-profile-info {
        padding-bottom: 0;
        width: 100%;
    }
    
    .gp-name-row {
        align-items: center;
        gap: 6px;
    }
    
    .gp-profile-name {
        font-size: 22px;
        line-height: 1.2;
        text-align: center; /* name-row centers on mobile; width:100% would otherwise left-align the text */
    }
    
    .gp-recruiting-badge,
    .gp-recruitment-badge {
        font-size: 11px;
        padding: 3px 10px;
    }
    
    .gp-profile-meta {
        justify-content: center;
        flex-wrap: wrap; /* long grad + location wrap to two centered lines instead of
                            overflowing the narrow header (each item stays intact). */
        gap: 8px 12px;
        font-size: 14px;
        margin-bottom: 8px;
    }
    
    .gp-events-badges {
        justify-content: center;
    }
    
    .gp-event-badge {
        font-size: 12px;
        padding: 3px 10px;
    }
    
    /* ----- Profile Actions (Edit/Star buttons) ----- */
    .gp-profile-actions {
        align-self: stretch;
        justify-content: center;
        width: 100%;
        gap: 8px;
    }
    
    .gp-profile-actions .gp-btn {
        flex: 1;
        max-width: 160px;
        justify-content: center;
        padding: 10px 16px;
        font-size: 13px;
    }
    
    .gp-profile-actions .gp-btn-star {
        flex: 1;
        max-width: 160px;
        justify-content: center;
        padding: 10px 16px;
        font-size: 13px;
    }
    
    /* ----- Tab Navigation ----- */
    .gp-tab-navigation {
        margin: 0 0 12px 0;
        border-radius: 0;
        padding: 2px;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    
    .gp-tab-navigation::-webkit-scrollbar {
        display: none;
    }
    
    .gp-tab-btn {
        padding: 12px 14px;
        font-size: 13px;
        min-width: max-content;
        flex: 1;
    }
    
    /* ----- Tab Content ----- */
    .gp-tab-content {
        padding: 0 12px;
    }
    
    /* ----- Cards ----- */
    :where(.gp-profile-wrapper) .gp-card {
        padding: 14px;
        border-radius: 12px;
        margin-bottom: 12px;
    }
    
    .gp-card-header {
        margin-bottom: 12px;
        padding-bottom: 10px;
    }
    
    .gp-card-title {
        font-size: 16px;
    }
    
    /* ----- Info Grid (About section) ----- */
    .gp-info-grid {
        grid-template-columns: 1fr;
        gap: 10px;
    }
    
    .gp-info-item {
        padding: 10px;
        gap: 10px;
    }
    
    .gp-info-icon {
        width: 36px;
        height: 36px;
    }
    
    .gp-info-icon svg {
        width: 18px;
        height: 18px;
    }
    
    .gp-info-label {
        font-size: 11px;
    }
    
    .gp-info-value {
        font-size: 14px;
    }
    
    /* ----- Introduction Video ----- */
    .gp-intro-video {
        margin: 0 -14px;
    }
    
    .gp-intro-video iframe {
        height: 200px;
        border-radius: 0;
    }
    
    /* ----- Bio Section ----- */
    .gp-bio-text {
        font-size: 14px;
        line-height: 1.6;
    }
    
    /* ----- Contact Toggle ----- */
    .gp-contact-toggle {
        padding: 10px 16px;
        font-size: 14px;
    }
    
    .gp-contact-content {
        margin-top: 12px;
    }
    
    /* ----- Support Team Section ----- */
    .gp-support-team-section {
        margin-top: 16px;
        padding-top: 14px;
    }
    
    .gp-section-subtitle {
        font-size: 13px;
        margin-bottom: 12px;
    }
    
    /* ----- Filter Buttons (Video tabs) ----- */
    .gp-subtab-navigation {
        flex-wrap: wrap;
        gap: 8px;
    }
    
    .gp-filter-buttons {
        width: 100%;
        order: 2;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        flex-wrap: nowrap;
        padding: 3px;
    }
    
    .gp-filter-buttons::-webkit-scrollbar {
        display: none;
    }
    
    .gp-filter-btn {
        padding: 8px 12px;
        font-size: 12px;
        white-space: nowrap;
        flex: 0 0 auto;
    }
    
    .gp-add-video-btn {
        order: 1;
        width: 100%;
        justify-content: center;
        margin-bottom: 4px;
        padding: 10px 16px;
        font-size: 13px;
    }
    
    /* ----- Card Header with Filters ----- */
    .gp-card-header-with-filters {
        flex-direction: column;
        gap: 10px;
        padding: 12px 14px;
    }
    
    .gp-card-header-with-filters .gp-filter-buttons {
        max-width: 100%;
        width: 100%;
        order: 2;
    }
    
    .gp-card-header-with-filters .gp-add-video-btn {
        order: 1;
        width: 100%;
        margin-bottom: 0;
    }
    
    /* ----- Video Grid ----- */
    .gp-video-grid {
        grid-template-columns: 1fr;
        gap: 16px;
    }
    
    /* ----- Video Cards ----- */
    .gp-video-card {
        border-radius: 10px;
    }
    
    .gp-video-card-thumbnail {
        aspect-ratio: 16 / 9;
    }
    
    .gp-video-play-overlay {
        width: 44px;
        height: 44px;
    }
    
    .gp-video-play-overlay svg {
        width: 18px;
        height: 18px;
        margin-left: 2px;
    }
    
    .gp-video-card-badges {
        top: 6px;
        left: 6px;
        gap: 4px;
    }
    
    .gp-video-badge {
        padding: 2px 6px;
        font-size: 9px;
        border-radius: 3px;
    }
    
    .gp-video-score-badge {
        top: 6px;
        right: 6px;
        padding: 3px 8px;
        font-size: 12px;
        border-radius: 4px;
    }
    
    .gp-video-card-body {
        padding: 10px 12px;
    }
    
    .gp-video-card-title {
        font-size: 13px;
        -webkit-line-clamp: 1;
        margin-bottom: 4px;
    }
    
    .gp-video-card-meta {
        font-size: 11px;
        gap: 4px 8px;
    }
    
    .gp-video-card-details {
        gap: 3px;
        font-size: 11px;
    }
    
    .gp-video-detail-row {
        gap: 4px;
    }
    
    .gp-video-detail-label {
        min-width: 50px;
        font-size: 10px;
    }
    
    .gp-video-detail-value {
        font-size: 11px;
    }
    
    .gp-video-description {
        font-size: 10px;
        -webkit-line-clamp: 1;
    }
    
    .gp-video-date {
        font-size: 10px;
        padding-top: 4px;
    }
    
    .gp-video-date svg {
        width: 12px;
        height: 12px;
    }
    
    /* ----- Video Menu (Edit/Delete) ----- */
    .gp-video-menu {
        bottom: 6px;
        right: 6px;
    }
    
    .gp-video-menu-btn {
        width: 32px;
        height: 32px;
        font-size: 14px;
        opacity: 1;
    }
    
    .gp-video-menu-dropdown {
        min-width: 120px;
    }
    
    .gp-video-menu-dropdown button {
        padding: 8px 12px;
        font-size: 12px;
    }
    
    /* ----- No Videos Message ----- */
    .gp-no-videos,
    .gp-no-filter-results {
        padding: 30px 16px;
        font-size: 14px;
    }
    
    .gp-no-videos svg,
    .gp-no-filter-results svg {
        width: 40px;
        height: 40px;
    }
    
    /* ----- Video Playback Modal ----- */
    .gp-video-modal {
        padding: 16px;
        align-items: center;
        justify-content: center;
    }
    
    .gp-video-modal-content {
        max-width: none;
        width: 100%;
        border-radius: 12px;
        max-height: 85vh;
        box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.08);
    }
    
    .gp-video-modal-player {
        aspect-ratio: 16 / 9;
        width: 100%;
    }
    
    .gp-video-modal-info {
        padding: 14px 16px;
        padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    
    .gp-video-modal-title {
        font-size: 16px;
        margin-bottom: 8px;
    }
    
    .gp-video-modal-meta {
        gap: 12px 16px;
        margin-bottom: 12px;
    }
    
    .gp-video-modal-meta-label {
        font-size: 10px;
    }
    
    .gp-video-modal-meta-value {
        font-size: 13px;
    }
    
    .gp-video-modal-description {
        font-size: 13px;
        padding-top: 10px;
    }
    
    /* ----- Edit/Add Modals ----- */
    /* Note: Core bottom-sheet styles moved to gp-mobile-single.css */
    /* Scoped :not(.gp-surface): see the modal-system note above; the shared
       More sheet must never receive these. */
    .gp-modal-overlay:not(.gp-surface) {
        padding: 0;
        align-items: flex-end;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal {
        max-height: 92vh;
        border-radius: 16px 16px 0 0;
        margin-top: auto;
        display: flex;
        flex-direction: column;
    }

    /* Modal header - sticky with safe area */
    .gp-modal-overlay:not(.gp-surface) .gp-modal-header {
        position: sticky;
        top: 0;
        z-index: 10;
        background: var(--gp-card-bg, #fff);
        padding: 14px 16px;
        padding-top: calc(14px + env(safe-area-inset-top, 0px));
        flex-shrink: 0;
    }
    
    .gp-modal-overlay:not(.gp-surface) .gp-modal-title {
        font-size: 17px;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-close {
        width: 32px;
        height: 32px;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-close svg {
        width: 20px;
        height: 20px;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-tabs {
        padding: 0 16px;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        flex-shrink: 0;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-tab {
        padding: 12px 16px;
        font-size: 13px;
        white-space: nowrap;
    }

    /* Modal body - flexible scroll area */
    .gp-modal-overlay:not(.gp-surface) .gp-modal-body {
        padding: 16px;
        flex: 1;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
        /* Remove hardcoded max-height - flexbox handles it */
    }

    /* Modal footer - sticky with safe area */
    .gp-modal-overlay:not(.gp-surface) .gp-modal-footer {
        position: sticky;
        bottom: 0;
        z-index: 10;
        background: var(--gp-bg-gray, #f5f5f5);
        padding: 12px 16px;
        padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
        gap: 10px;
        flex-shrink: 0;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-footer .gp-btn {
        padding: 12px 20px;
        font-size: 14px;
    }
    
    /* ----- Form Styles ----- */
    .gp-form-section {
        margin-bottom: 20px;
    }
    
    .gp-form-section-title {
        font-size: 12px;
        margin-bottom: 12px;
    }
    
    .gp-form-group {
        margin-bottom: 14px;
    }
    
    .gp-form-label {
        font-size: 13px;
        margin-bottom: 5px;
    }
    
    .gp-form-input,
    .gp-form-select,
    .gp-form-textarea {
        padding: 10px 12px;
        font-size: 14px;
        border-radius: 8px;
    }
    
    .gp-form-textarea {
        min-height: 80px;
    }
    
    .gp-form-hint {
        font-size: 11px;
    }
    
    .gp-form-row {
        grid-template-columns: 1fr;
        gap: 14px;
    }
    
    .gp-form-radio-group {
        gap: 6px;
    }
    
    .gp-form-radio label {
        padding: 8px 12px;
        font-size: 13px;
    }
    
    /* ----- Photo Upload ----- */
    .gp-photo-upload {
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
    }
    
    .gp-photo-preview {
        width: 70px;
        height: 70px;
    }
    
    /* ----- Toast Notifications ----- */
    .gp-toast-container {
        left: 12px;
        right: 12px;
        bottom: 24px;
    }
    
    .gp-toast {
        width: 100%;
        padding: 12px 16px;
        font-size: 13px;
        border-radius: 10px;
    }
    
    /* ----- Delete Confirmation ----- */
    .gp-delete-warning {
        padding: 16px 0;
    }
    
    .gp-delete-icon {
        width: 56px;
        height: 56px;
        margin-bottom: 12px;
    }
    
    .gp-delete-icon svg {
        width: 28px;
        height: 28px;
    }
    
    .gp-delete-warning p {
        font-size: 14px;
    }
}

/* -----------------------------------------
   SMALL MOBILE BREAKPOINT (480px and below)
   ----------------------------------------- */
@media (max-width: 480px) {
    .gp-profile-photo {
        width: 168px;
        height: 168px;
    }
    
    .gp-profile-name {
        font-size: 20px;
    }
    
    .gp-recruiting-badge,
    .gp-recruitment-badge {
        font-size: 10px;
        padding: 2px 8px;
    }
    
    .gp-profile-meta {
        font-size: 13px;
    }
    
    .gp-profile-actions .gp-btn,
    .gp-profile-actions .gp-btn-star {
        max-width: 140px;
        padding: 8px 12px;
        font-size: 12px;
    }
    
    .gp-tab-btn {
        padding: 10px 12px;
        font-size: 12px;
    }
    
    :where(.gp-profile-wrapper) .gp-card {
        padding: 12px;
        border-radius: 10px;
    }
    
    .gp-card-title {
        font-size: 15px;
    }
    
    /* Single column video grid on very small screens */
    .gp-video-grid {
        grid-template-columns: 1fr;
        gap: 12px;
    }
    
    .gp-video-card-thumbnail {
        aspect-ratio: 16 / 9;
    }
    
    .gp-video-card-title {
        font-size: 14px;
        -webkit-line-clamp: 2;
    }
    
    .gp-video-card-details {
        font-size: 12px;
    }
    
    .gp-filter-btn {
        padding: 7px 10px;
        font-size: 11px;
    }
    
    .gp-add-video-btn {
        padding: 8px 14px;
        font-size: 12px;
    }
    
    .gp-intro-video iframe {
        height: 180px;
    }
    
    .gp-modal-overlay:not(.gp-surface) .gp-modal-body {
        padding: 14px;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-header,
    .gp-modal-overlay:not(.gp-surface) .gp-modal-footer {
        padding: 12px 14px;
    }

    .gp-modal-overlay:not(.gp-surface) .gp-modal-title {
        font-size: 16px;
    }
    
    .gp-form-input,
    .gp-form-select,
    .gp-form-textarea {
        padding: 10px;
        font-size: 14px;
    }
}

/* -----------------------------------------
   EXTRA SMALL SCREENS (360px and below)
   ----------------------------------------- */
@media (max-width: 360px) {
    .gp-profile-photo {
        width: 150px;
        height: 150px;
    }
    
    .gp-profile-name {
        font-size: 18px;
    }
    
    .gp-profile-actions {
        flex-direction: column;
        gap: 6px;
    }
    
    .gp-profile-actions .gp-btn,
    .gp-profile-actions .gp-btn-star {
        max-width: 100%;
        width: 100%;
    }
    
    .gp-tab-btn {
        padding: 8px 10px;
        font-size: 11px;
    }
    
    .gp-filter-btn {
        padding: 6px 8px;
        font-size: 10px;
    }
}
/* ========================================
   PRINT STYLES
   ======================================== */
@media print {
    .gp-profile-actions,
    .gp-add-video-btn,
    .gp-video-menu,
    .gp-modal-overlay,
    .gp-video-modal,
    .gp-toast-container {
        display: none !important;
    }
}

/* ========================================
   IMAGE CROPPING & REPOSITIONING
   Profile photo cropping (Cropper.js)
   Cover photo repositioning (drag to adjust)
   ======================================== */

/* ----- Profile Photo Crop Modal ----- */
.gp-crop-modal {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.95);
    z-index: 100003; /* Above edit modal (10001) */
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px;
    /* Opened as a native <dialog> (showModal) so it nests in the top layer ABOVE
       the edit cover. Neutralize the dialog UA box model. */
    max-width: none;
    max-height: none;
    width: auto;
    height: auto;
    margin: 0;
    border: 0;
}
/* showModal() sets [open], not the legacy .active class. */
dialog.gp-crop-modal[open] {
    display: flex;
}
/* The dialog's own near-opaque bg is the scrim; keep the native backdrop clear. */
dialog.gp-crop-modal::backdrop {
    background: transparent;
}

.gp-crop-modal.active {
    display: flex;
}

.gp-crop-container {
    width: 100%;
    max-width: 500px;
    background: #1a1a1a;
    border-radius: 12px;
    overflow: hidden;
}

.gp-crop-preview {
    width: 100%;
    height: 400px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #000;
    position: relative;
}

.gp-crop-preview img {
    max-width: 100%;
    max-height: 100%;
    display: block;
}

/* Cropper.js circular crop guide - IMPORTANT */
.gp-crop-modal .cropper-view-box,
.gp-crop-modal .cropper-face {
    border-radius: 50% !important;
}

.gp-crop-modal .cropper-view-box {
    box-shadow: 0 0 0 1px #DFB859 !important;
    outline: 0 !important;
}

/* Darken corners to show what will be hidden in circular display */
.gp-crop-modal .cropper-face {
    background-color: transparent !important;
}

.gp-crop-modal .cropper-crop-box::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
    pointer-events: none;
}

/* Hide the dashed lines but keep the circular guide */
.gp-crop-modal .cropper-dashed {
    display: none !important;
}

/* Make the crop area more visible */
.gp-crop-modal .cropper-modal {
    background-color: rgba(0, 0, 0, 0.7) !important;
}

/* Center guides */
.gp-crop-modal .cropper-center {
    display: none !important;
}

/* ----- Crop Controls ----- */
.gp-crop-controls {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 20px;
    background: #1a1a1a;
}

.gp-crop-zoom {
    display: flex;
    align-items: center;
    gap: 12px;
}

.gp-crop-zoom label {
    color: #999;
    font-size: 13px;
    min-width: 50px;
}

.gp-crop-zoom input[type="range"] {
    flex: 1;
    height: 6px;
    background: #333;
    border-radius: 3px;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    outline: none;
}

.gp-crop-zoom input[type="range"]::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    width: 20px;
    height: 20px;
    background: #DFB859;
    border-radius: 50%;
    cursor: pointer;
    transition: transform 0.15s ease;
    border: none;
}

.gp-crop-zoom input[type="range"]::-webkit-slider-thumb:hover {
    transform: scale(1.15);
}

.gp-crop-zoom input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    background: #DFB859;
    border-radius: 50%;
    border: none;
    cursor: pointer;
}

.gp-crop-zoom input[type="range"]::-moz-range-track {
    background: #333;
    height: 6px;
    border-radius: 3px;
}

.gp-crop-actions {
    display: flex;
    gap: 12px;
    justify-content: flex-end;
}

.gp-crop-actions .gp-btn {
    min-width: 100px;
    padding: 12px 24px;
}

.gp-crop-hint {
    color: #666;
    font-size: 12px;
    text-align: center;
    margin: 0;
}

/* ----- Cover Photo Repositioning ----- */
.gp-cover-upload {
    flex-direction: column;
    align-items: stretch;
}

.gp-cover-preview {
    width: 100%;
    aspect-ratio: 4 / 1; /* Match .gp-cover-photo proportions (full-width x 200px) */
    border-radius: 8px;
    background: var(--gp-bg-gray);
    overflow: hidden;
    border: 2px dashed var(--gp-border-color);
    position: relative;
}

.gp-cover-preview.has-image {
    border-style: solid;
    border-color: transparent;
}

.gp-cover-preview img {
    width: 100%;
    height: 100%; /* Match .gp-cover-photo img rendering so preview = display */
    object-fit: cover;
    object-position: center 50%;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
}

.gp-cover-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    gap: 8px;
    color: #999;
    font-size: 13px;
}

/* Cover reposition mode */
.gp-cover-reposition-mode {
    cursor: grab;
    border: 2px solid #DFB859 !important;
}

.gp-cover-reposition-mode:active {
    cursor: grabbing;
}

.gp-cover-reposition-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 14px;
    font-weight: 500;
    gap: 10px;
    pointer-events: none;
    z-index: 10;
}

.gp-cover-reposition-overlay svg {
    animation: gpBounceVertical 1s ease-in-out infinite;
}

@keyframes gpBounceVertical {
    0%, 100% { transform: translateY(-4px); }
    50% { transform: translateY(4px); }
}

/* The .gp-upload-overlay family is styled by injectUploadStyles() in
   gp-profile.js (single source; do not restyle it here). The 80px avatar
   circle is too small for the overlay label, so the trigger button carries
   the "Preparing photo..." text there (see beginPreparingPhoto). */
.gp-photo-preview .gp-upload-overlay__label {
    display: none;
}

/* Cover confirm actions (wrong-photo protection): shown below the picked
   image until the member taps Use this photo or Cancel. Same row idiom as
   .gp-cover-reposition-actions so both states read as one control area. */
.gp-cover-confirm {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.gp-cover-confirm .gp-btn {
    flex: 1;
    font-size: 13px;
    padding: 12px;
}

/* Cover reposition actions */
.gp-cover-reposition-actions {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.gp-cover-reposition-actions .gp-btn {
    flex: 1;
    font-size: 13px;
    padding: 10px 12px;
}

.gp-cover-reposition-actions .gp-btn-delete {
    flex: 0 0 auto;
    padding: 10px 16px;
}

/* Profile photo upload area adjustments */
.gp-photo-upload .gp-photo-preview {
    cursor: pointer;
    transition: border-color 0.2s ease, transform 0.2s ease;
}

.gp-photo-upload .gp-photo-preview:hover {
    border-color: var(--gp-accent-gold);
    transform: scale(1.02);
}

/* Profile header cover photo with position support */
/* object-position is applied via inline style from cover_photo_position_y */

/* ----- Mobile Adjustments ----- */
@media (max-width: 768px) {
    .gp-crop-modal {
        padding: 10px;
    }
    
    .gp-crop-container {
        max-width: 100%;
    }
    
    .gp-crop-preview {
        height: 300px;
    }
    
    .gp-crop-controls {
        padding: 16px;
    }
    
    .gp-crop-actions {
        flex-direction: row;
    }
    
    .gp-crop-actions .gp-btn {
        flex: 1;
        min-width: auto;
    }
    
    .gp-cover-preview {
        /* aspect-ratio from main rule handles responsive sizing */
    }
    
    .gp-cover-reposition-actions {
        flex-wrap: wrap;
    }
    
    .gp-cover-reposition-actions .gp-btn {
        flex: 1 1 auto;
        min-width: 80px;
    }
}

/* ==========================================================================
   COLLEGE VISITS — edit form rows + public badge display (Phase 3, B2 lane)
   ========================================================================== */

/* Edit form — repeater rows (mirrors .gp-acc-list / .gp-acc-row) */
.gp-visit-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}

.gp-visit-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.gp-visit-row .gp-visit-university {
    flex: 1;
    min-width: 0;
}

.gp-visit-row .gp-visit-date {
    width: 150px;
    flex-shrink: 0;
}

.gp-visit-remove {
    background: none;
    border: none;
    color: var(--gp-color-text-muted);
    cursor: pointer;
    font-size: 20px;
    line-height: 1;
    padding: 0 4px;
    flex-shrink: 0;
    transition: color 0.15s ease;
}

.gp-visit-remove:hover {
    color: var(--gp-color-danger);
}

/* Public card — badge row */
.gp-visits-block {
    padding: 0;
}

.gp-visits-badge-row {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    padding: 4px 0;
    align-items: flex-start;
}

.gp-visit-badge-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    cursor: default;
}

.gp-visit-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.gp-visit-badge--sm { width: 40px;  height: 40px;  font-size: 10px; }
.gp-visit-badge--md { width: 68px;  height: 68px;  font-size: 13px; }
.gp-visit-badge--lg { width: 88px;  height: 88px;  font-size: 15px; }

.gp-visit-badge img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.gp-visit-badge__abbr {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    letter-spacing: 0.02em;
    font-weight: 700;
    color: var(--gp-color-text);
    background: var(--gp-color-surface-2);
    border-radius: 6px;
}

.gp-visit-badge-date {
    font-size: 10px;
    color: var(--gp-color-text-muted);
    text-align: center;
    line-height: 1.2;
    white-space: nowrap;
}

/* -----------------------------------------------------------------------
   School Interest ("Liked By") — profile card + per-video badges
   ----------------------------------------------------------------------- */
.gp-likes-badges-wrap {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.gp-likes-badge-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}

.gp-likes-badge-item {
    display: inline-flex;
}

/* Per-video likes — compact row inside the video card body */
.gp-video-likes {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--gp-color-border);
}

.gp-video-likes .gp-likes-badge-row {
    gap: 4px;
}

/* School interest card — hide the header bottom border when it's the only content */
.gp-school-interest-card .gp-card-body {
    padding-top: 12px;
}

/* Mobile adjustments */
@media (max-width: 640px) {
    .gp-visit-row {
        flex-wrap: wrap;
    }

    .gp-visit-row .gp-visit-university {
        width: 100%;
        flex: none;
    }

    .gp-visit-row .gp-visit-date {
        flex: 1;
        width: auto;
    }
}

/* ==========================================================================
   DARK MODE, PASS 2 (Podium design pass, UB 2026-07-25) — two buttons in
   page-templates/single-gymnast_profile.php set their color via an inline
   `style=""` attribute (the crop modal's "Apply" button, id=applyCropBtn; the
   access-restricted modal's "Request access" link, inside
   #accessRestrictedModal), which beats normal stylesheet specificity — the
   ONLY way to override it without editing that inline style (and risking a
   light-mode pixel diff, since the two attributes are hand-picked values, not
   a token reference) is a scoped `!important` on the exact element. Same
   precedent already used in this codebase for the identical problem (see
   css/gp-recruiting-portal.css .gp-rp-subsection-header, which wins over a
   per-section inline pastel the same way). Light is untouched: the inline
   attribute itself is never touched, so light renders the exact same bytes
   it always did. */
[data-theme="dark"] #applyCropBtn {
    background: var(--gp-color-primary) !important;
    color: var(--gp-color-on-primary) !important;
}
[data-theme="dark"] #accessRestrictedModal .gp-btn-primary {
    background: var(--gp-color-primary) !important;
    border-color: var(--gp-color-primary) !important;
    color: var(--gp-color-on-primary) !important;
}
