/*
 * STRYNE — the phone layer.
 *
 * Every rule here lives inside a media query, so a desktop browser matches
 * none of them. That is deliberate: the desktop layout is the one that works
 * today and it must not move. Nothing below is reachable above 1100px, and
 * almost nothing above 768px — the width at which main.css already swaps the
 * fixed sidebar for the hamburger.
 *
 * It is linked LAST in every <head>, after main.css and after the page's own
 * <style> block, because most pages re-declare their grids inline and would
 * otherwise win the cascade on equal specificity. The `!important` marks are
 * reserved for grids written straight into a `style=` attribute in the HTML,
 * which no stylesheet can outrank any other way.
 *
 *   1. Tablet band (769-1100px) — the sidebar is still pinned here.
 *   2. Phone (<=768px) — shell, topbar, forms, buttons, tables, modals.
 *   3. Phone, coach pages.
 *   4. Phone, athlete portal.
 *   5. Login screens.
 *   6. Narrow phone (<=420px).
 *   7. rutinas.php — the set editor and the exercise picker, which run out
 *      of room well before the sidebar goes away and need their own band.
 */


/* ═══════════════════════════════════════════════════════════════════
   1. TABLET BAND — 769px to 1100px
   The sidebar is still 260px and pinned, so the content column is far
   narrower than the viewport these pages measure themselves against.
   Several of them only relax their grids at 600px and end up squeezing
   five columns into ~340px. Bounded on both sides, so real desktop
   widths (>=1101px) match nothing here.
   ═══════════════════════════════════════════════════════════════════ */
@media (min-width:769px) and (max-width:1100px) {
    /* Same root cause as on the phone: `.main` is a flex item with no floor,
       so a wide table stretched it past the window instead of scrolling. An
       iPad in portrait (820px) is squarely inside this band. */
    .main { min-width:0; }

    /* bienestar_atleta.php has five tiles here, rendimiento_atleta.php four. */
    .stats-row { grid-template-columns:repeat(2,1fr); }

    /* These four pages stack their athlete rail above the content at 860px
       (900px in historial_entrenos.php), inside this band. Stretched, a wide
       table scrolls in its card instead of widening the page — the phone
       rule of the same name explains why. Above those widths they are rows,
       and stretching changes nothing visible: neither column has a
       background of its own. */
    .rp-layout, .rd-layout, .bw-layout, .hist-layout { align-items:stretch; }

    /* mensajeria.php keeps its two panes side by side until the sidebar
       leaves at 768, so between 769px and here the 260px sidebar and a 260px
       conversation list left the chat about 220px. Give the list less. */
    .msg-left { width:200px; }
    .msg-right { min-width:0; }
    .input-row { flex-wrap:wrap; }

    /* rutinas.php keeps its 210px athlete rail until 768px too. */
    .ent-left { width:170px; }

    /* The wide tables scroll inside their card rather than pushing the page. */
    .user-table { min-width:560px; }
    .perm-tabla { min-width:420px; }
    .w-table, .hist-tbl, .seg-table { min-width:0; }
    .pcard { min-width:0; }
    .pcard-body { overflow-x:auto; }
    .comp-tbl { min-width:480px; }
    .content .sec-card, .content .section-card { min-width:0; }

    /* perfil_atleta.php: the grids written into `style=` attributes are as
       fixed here as they are on a phone. */
    div[style*="grid-template-columns:280px 1fr"] { grid-template-columns:1fr !important; }
    .comp-strip { grid-template-columns:1fr 1fr; }
}


/* ═══════════════════════════════════════════════════════════════════
   2. PHONE — 768px and below: the shared shell
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:768px) {

/* ── 2.1 Shell ──────────────────────────────────────────────────────
   `body` is a flex row and `.main` is its flex item. Without min-width:0 a
   flex item refuses to shrink below the intrinsic width of its content, so
   one wide table or one non-wrapping row stretched `.main` to 750-850px and
   pushed the entire page sideways — measured, the single largest cause of
   horizontal scrolling in this app. Scoped to the phone because on desktop
   that same growth is what lets a wide table push the layout out rather
   than be clipped. */
.main { min-width:0; }

.content { padding:16px 14px; }

/* ── 2.2 Topbar ─────────────────────────────────────────────────────
   64px tall, no wrap, and a title made of a heading plus a subtitle. On a
   phone the subtitle wrapped to three lines inside a box that cannot grow,
   so it spilled over the row below. One line each, ellipsised. */
/* The phone keeps the shorter bar: the extra breathing room the desktop
   gained is a fifth of a small screen. */
:root { --topbar-h:64px; }
.topbar { padding:0 12px; gap:10px; }
.topbar-title { min-width:0; }
.topbar-title h2,
.topbar-title p {
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.topbar-title h2 { font-size:15px; }
.topbar-title p  { font-size:11px; }
.topbar-actions { flex-shrink:0; }

/* 36px is below what a thumb reliably hits. 40px is the compromise that
   does not force every toolbar to grow a second row. */
.hamburger, .icon-btn { width:40px; height:40px; flex-shrink:0; }

/* ── 2.3 Page header and actions ───────────────────────────────────
   Header is icon + title + (sometimes) a button group the page pushes
   right with margin-left:auto. At this width the group landed on top of
   the subtitle. Let the row wrap and give the group a line of its own. */
.page-header { flex-wrap:wrap; gap:12px; margin-bottom:18px; }
.page-header-icon { width:42px; height:42px; font-size:18px; }
.page-header h1 { font-size:18px; }
.page-header p  { font-size:12px; }
.page-header .ph-actions,
.page-header .page-actions { width:100%; margin-left:0; flex-wrap:wrap; }
.ph-actions { flex-wrap:wrap; }

/* main.css sets justify-content:stretch here, which is not a valid flex
   value and silently falls back to flex-start. Say what was meant. */
.page-actions { justify-content:flex-start; }
.page-actions .izq { margin-right:0; }

/* ── 2.4 Forms ──────────────────────────────────────────────────────
   16px is not a style choice: iOS Safari zooms the page in whenever a
   focused field is smaller than that, and with initial-scale=1 and no
   maximum-scale it never zooms back out — the athlete is left panned
   sideways mid-set. Every field in this app was 11-13.5px. */
.form-input, .form-select, .form-textarea,
input[type=text], input[type=number], input[type=password],
input[type=email], input[type=date], input[type=search], input[type=tel],
select, textarea {
    font-size:16px;
    min-height:44px;
}
textarea, .form-textarea { min-height:88px; }
.form-label { font-size:11.5px; }

.btn-primary, .btn-secondary {
    min-height:44px; font-size:14px; justify-content:center;
}
.btn-row { flex-wrap:wrap; gap:8px; }
.btn-row > * { flex:1 1 auto; }

/* ── 2.5 Cards and grids main.css owns ─────────────────────────────── */
/* The section header is icon + title + a button the page pushes right with
   margin-left:auto. Without a wrap the button sat on top of the subtitle. */
.sec-card-header { padding:14px 16px; gap:10px; flex-wrap:wrap; }
.sec-card-body   { padding:16px; }
.sec-card-header .sec-texts { flex:1 1 auto; min-width:0; }
.sec-card-header .sec-texts h3 { font-size:13px; }
.sec-card-header > .btn-primary,
.sec-card-header > .btn-secondary {
    margin-left:0 !important; flex:1 1 100%;
}

.mini-stats { grid-template-columns:repeat(2,1fr); gap:10px; }
.mini-stat  { padding:14px; }
.mini-stat .ms-val { font-size:22px; }
.wear-grid { grid-template-columns:1fr; }

/* ── 2.6 Tables ─────────────────────────────────────────────────────
   Most tables already sit in a div with overflow-x:auto, but the table is
   width:100% with no floor, so instead of scrolling they squeezed seven or
   eight columns into 340px. A min-width makes the wrapper do its job. */
.sec-card-body[style*="overflow-x"] > table,
div[style*="overflow-x"] > table { min-width:520px; }

/* A scroll container inside a padded card loses its right-hand padding the
   moment it scrolls; move the padding onto the scroller itself. */
.sec-card-body[style*="overflow-x"] { padding:0 0 4px; }
.sec-card-body[style*="overflow-x"] > table { margin:0; }

/* ── 2.7 Modals ─────────────────────────────────────────────────────
   Shared behaviour for every `.modal-bg` / `.modal` in the app. Three of
   them (usuarios.php) had no padding on the backdrop and no scrolling at
   any level: on a short screen the submit button sat below the fold with
   no way to reach it. Three more (ejercicios.php) sat flush against both
   edges of the screen. Here they all become one sheet, anchored to the
   bottom where the thumb is, with the body scrolling inside it. */
.modal-bg,
.im-bg {                       /* rutinas.php's bulk import uses its own names */
    padding:0 !important;
    align-items:flex-end !important;
    justify-content:center;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
}
.im {
    max-width:none !important;
    border-radius:18px 18px 0 0 !important;
    max-height:92dvh;
    display:flex; flex-direction:column;
}
.im-bd { overflow-y:auto; -webkit-overflow-scrolling:touch; }
.modal {
    width:100% !important;
    max-width:none !important;
    margin:0 !important;
    padding:20px 16px calc(20px + env(safe-area-inset-bottom)) !important;
    border-radius:18px 18px 0 0 !important;
    max-height:92dvh;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
}
/* The close glyph was a bare 18-22px character with no box around it. */
.modal-close, .im-x {
    width:40px; height:40px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    border-radius:10px;
}
.modal .btn-row, .modal-foot { flex-wrap:wrap; }

/* The shared confirm dialog already handles itself (confirmar.css) but only
   stacks its buttons below 480px. */
.cfm-pie { flex-direction:column-reverse; }
.cfm-btn { width:100%; }

/* toast.css moves the stack to the bottom of the screen at 520px, where it
   lands on top of any bar a page has pinned there. Lift it clear. */
body:has(.bottom-bar) .toast-stack,
body:has(.form-actions) .toast-stack { bottom:96px; }
/* portal/entrenamiento.php's bar also carries the progress strip on step 2. */
body:has(.bb-prog:not([hidden])) .toast-stack { bottom:136px; }

} /* end 2 */


/* ═══════════════════════════════════════════════════════════════════
   3. PHONE — coach pages
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:768px) {

/* ── dashboard.php ─────────────────────────────────────────────────
   Four stat tiles the page forces to two columns at 600px. Two columns at
   375px leaves about 100px of usable width, and main.css makes the tile a
   flex row (icon beside the number), so the label was cut off by the
   tile's own overflow:hidden. Stack the tile instead of splitting it. */
.stats-grid { grid-template-columns:repeat(2,1fr); gap:10px; }
.stat-card {
    flex-direction:column; align-items:flex-start; gap:8px;
    padding:14px; overflow:visible;
}
.stat-icon { width:36px; height:36px; font-size:15px; margin-bottom:0; }
/* The period picker of the sessions tile cannot sit in a corner this narrow:
   it goes above the figure, across the tile, and is still one tap. */
.stat-seg { margin-left:0; width:100%; }
.stat-seg button { flex:1; padding:5px 4px; font-size:10px; }
.stat-value { font-size:24px; }
.stat-label {
    font-size:10.5px; letter-spacing:.2px; margin-bottom:0;
    white-space:normal; line-height:1.3;
}
.stat-trend { font-size:11px; flex-wrap:wrap; }

/* The "Mis Atletas" header put a title, an "Agregar" link and three filter
   chips on one non-wrapping row; they printed over each other. */
.sec-header {
    flex-wrap:wrap; gap:10px; padding:14px 16px;
    justify-content:flex-start;
}
.sec-header h3 { font-size:14px; }
.filter-tabs { width:100%; gap:6px; }
.filter-tabs .ftab { flex:1; text-align:center; padding:9px 8px; font-size:12px; }

/* One athlete row reserved 272px for avatar + progress bar + count + dot
   before the name had any room at all, so name, percentage and "Sin
   sesiones" overlapped. Two lines, no fixed widths. */
.atleta-row { flex-wrap:wrap; gap:10px; padding:12px 16px; }
.atleta-info { flex:1 1 60%; }
.atleta-meta { flex-wrap:wrap; gap:6px; font-size:11px; }
.pct-bar-wrap { width:auto; flex:1 1 100%; order:3; }
.pct-label { text-align:left; }
.sesiones-count { width:auto; text-align:right; }

.main-grid { grid-template-columns:1fr; }
.t-item { padding:10px 16px; }
.deporte-row { padding:10px 16px; }

/* "Lo que reportaron tus atletas". Five wellness chips beside a name leave the
   name about ninety pixels, so the chips take a line of their own underneath
   and the name gets the width it needs. */
.act-ses { padding:14px 16px; }
.act-quien { flex:1 1 100%; }
.act-well { width:100%; }

/* The five-column reading — exercise, planned, actual, weight delta, RPE — is
   about 480px wide as a table, and squeezing it here broke PLANIFICADO across
   two lines and each exercise name across three. The same five values become
   three short rows instead, and the column header goes: each cell now says its
   own name, which is what the header was for. */
.act-cab { display:none; }
.act-fila { grid-template-columns:1fr 1fr auto; gap:3px 8px; padding:9px 0; }
.act-fila .act-ej      { grid-column:1 / 3; grid-row:1; }
.act-fila .act-rpe     { grid-column:3; grid-row:1; text-align:right; }
.act-fila .act-plan    { grid-column:1; grid-row:2; text-align:left; }
.act-fila .act-real    { grid-column:2; grid-row:2; text-align:left; }
.act-fila .act-d       { grid-column:3; grid-row:2; text-align:right; }
.act-fila .act-nota-ej { grid-column:1 / -1; grid-row:3; }
.act-plan::before, .act-real::before, .act-rpe::before {
    font-size:9px; font-weight:700; letter-spacing:.4px;
    text-transform:uppercase; color:var(--muted);
    margin-right:4px;
}
.act-plan::before { content:"Plan"; }
.act-real::before { content:"Real"; }
.act-rpe::before  { content:"Esfuerzo"; }

/* ── atletas.php ───────────────────────────────────────────────────
   minmax(290px,1fr) is wider than the content column on the narrowest
   phones, which forced a couple of pixels of sideways scroll. */
.atleta-grid { grid-template-columns:1fr; gap:14px; }
.toolbar { gap:8px; }
.search-wrap { flex:1 1 100%; }
.ac-actions { flex-wrap:wrap; }
.btn-edit, .btn-del { min-height:40px; padding:9px 14px; }

/* ── perfil_atleta.php ─────────────────────────────────────────────
   Eight fixed grids and not one media query. Several are written into
   `style=` attributes in the HTML, which is why the attribute selectors
   below carry !important — there is no other way to reach them. */
.ath-hdr { flex-wrap:wrap; gap:14px; }
.ath-photo, .ath-photo-placeholder { width:64px; height:64px; }
.ath-meta { flex:1 1 100%; min-width:0; }
.ath-name-row h1 { font-size:20px; }
.ath-fields { flex-wrap:wrap; gap:14px 20px; }

.comp-strip { grid-template-columns:1fr; gap:12px; }
.cs-divider { display:none; }
.train-stats { grid-template-columns:repeat(2,1fr); }
.sec-grid { grid-template-columns:1fr; }
.body-wrap { flex-wrap:wrap; }
.time-filters { flex-wrap:wrap; gap:6px; }
.time-filters .tf { min-height:36px; padding:8px 12px; font-size:12px; }
.hist-tbl .act-btn { width:36px; height:36px; }
.chart-tabs .cht-btn { min-height:40px; }

/* The grids that exist only in a `style=` attribute, which no stylesheet
   can reach any other way. There are exactly seven in the app, and these
   selectors cover every one of them — two chart pairs
   (bienestar_atleta.php:276, rendimiento_atleta.php:271), the objective /
   save-as pair in the session builder (rutinas.php:739), and four in
   perfil_atleta.php (599, 695, 767, plus the exercise rows below). */
div[style*="grid-template-columns:1fr 1fr 1fr"],
div[style*="grid-template-columns:1fr 1fr"],
div[style*="grid-template-columns:280px 1fr"] {
    grid-template-columns:1fr !important;
}
/* ...except the exercise rows, which read as a table and stay in columns. */
.lt-ej-row,
div[style*="grid-template-columns:1fr 80px 80px"] {
    grid-template-columns:1fr 62px 62px !important;
    font-size:11px;
}

/* A six-column table inside a card that clips its own overflow: it was
   being cut off rather than scrolled. The card also needed a floor of its
   own — as a grid item its default min-width:auto let the table push the
   card past the edge of the screen instead of scrolling inside it. */
.pcard { min-width:0; }
.pcard-body { overflow-x:auto; }
.comp-tbl { min-width:480px; }
.dta-tbl td, .dta-tbl th { padding:8px 6px; }

/* Same reasoning, applied to every grid and flex child inside the content
   column: on a phone a child that refuses to shrink does not "keep its
   size", it drags the whole page sideways. */
.content .pcard,
.content .sec-card,
.content .section-card,
.content .det-card,
.content .rp-card { min-width:0; }

/* ── equipos.php ───────────────────────────────────────────────────── */
.eq-layout { flex-direction:column; }
.eq-left { width:100%; }
.eq-hero { flex-wrap:wrap; padding:16px; gap:12px; }
.eq-item { padding:14px; }
.eq-nm { min-width:0; overflow:hidden; text-overflow:ellipsis; }
.member-card { flex-wrap:wrap; padding:12px; }
.btn-rm { min-height:38px; padding:8px 14px; font-size:12px; }
.eq-center form[style*="display:flex"] { flex-wrap:wrap; }

/* ── usuarios.php ──────────────────────────────────────────────────
   Three tables and a permission matrix of 17px checkboxes. */
.user-table { min-width:560px; font-size:13px; }
.perm-tabla { min-width:420px; }
.perm-tabla input[type=checkbox] { width:22px; height:22px; min-height:0; }
.perm-tabla td { padding:12px 10px; }
.btn-xs { min-height:38px; padding:9px 14px; font-size:12.5px; }
.action-row { gap:8px; }

/* ── calendario.php ────────────────────────────────────────────────
   Seven columns of 47px, each event label clipped to two or three
   characters. The grid stays — a month view that turns into a list stops
   being a month view — but the cells shrink to what a phone can show: the
   day number and one coloured dot per session. The list of sessions under
   the grid already carries the readable version. */
.cal-nav { flex-wrap:wrap; gap:10px; }
.cal-nav h2 { font-size:18px; flex:1 1 100%; order:-1; }
.cal-nav-btn { min-height:40px; }
.cal-dow { padding:7px 2px; font-size:9.5px; letter-spacing:0; }
.cal-day { min-height:62px; padding:4px 3px; }
.day-num { width:22px; height:22px; font-size:11.5px; }
.cal-event {
    font-size:0; padding:0; margin:3px 3px 0 0;
    height:7px; width:7px; border-radius:50%; border:0;
    display:inline-block; vertical-align:top;
}
/* The label carried its state as a 12%-opacity background behind readable
   text. As a dot there is no text left to read, so the state has to be the
   dot itself — at full strength. */
.cal-event.ev-realizada { background:#10b981; }
.cal-event.ev-pendiente { background:#f5c518; }
.cal-event.ev-atrasada  { background:#ef4444; }
.more-badge { font-size:9px; }
.ev-row { flex-wrap:wrap; gap:10px; padding:12px 0; }
.ev-fecha { flex-shrink:0; }

/* ── mensajeria.php ────────────────────────────────────────────────
   The conversation list stacked above the chat, and the pair held to the
   screen's height (topbar 64px + the content's 16px top padding, 12px
   left below) rather than to their content's. Left to grow, the thread
   pushed the box to write in below every message it held and the page
   scrolled instead of the thread — chat.js scrolls the thread's own box
   to the newest line. dvh follows the phone's toolbar where the browser
   has it; vh is the fallback. The list keeps a fixed share and scrolls
   on its own: two and a half rows, so it reads as scrollable. Scoped to
   .msg-layout because portal/mensajes.php shares the chat's classes. */
.msg-layout { flex-direction:column; height:calc(100vh - 92px); height:calc(100dvh - 92px); min-height:420px; }
.msg-left  { width:100%; max-height:156px; flex-shrink:0; border-right:0; border-bottom:1px solid rgba(255,255,255,.08); }
.msg-right { flex:1; min-height:0; }
.msg-layout .conv-item { padding:10px 14px; }
.msg-layout .chat-body { padding:14px 12px; }
.msg-layout .chat-input { padding:10px 12px; }
.bubble-wrap { max-width:85%; }
.input-row { gap:8px; }
.msg-textarea { font-size:16px; }
.btn-send { min-height:44px; }
.chat-header { padding:12px 14px; }

/* ── reportes · rendimiento_atleta · bienestar_atleta ──────────────
   Same shape: a fixed-width athlete rail beside the content, plus stat
   rows of four or five. */
/* Stacked, each column must take the full width. The pages lay these rows
   out with align-items:flex-start, which in a column sizes the content to
   fit what is inside it — so opening a session in historial_entrenos.php
   stretched the whole page to the width of its exercise table (757px on a
   375px phone) instead of letting the table scroll in its own box. */
.rp-layout, .rd-layout, .bw-layout, .hist-layout { flex-direction:column; align-items:stretch; }
.rp-left, .rd-left, .bw-left, .hist-left { width:100%; }
.rp-card-hdr { flex-wrap:wrap; gap:8px; }
.rp-card-body[style*="display:flex"] { flex-wrap:wrap; }
.info-row { flex-wrap:wrap; gap:4px; }
.info-row > div[style*="display:flex"] { flex-wrap:wrap; gap:10px; }
/* .stats-row is deliberately NOT touched here: bienestar_atleta.php and
   rendimiento_atleta.php each relax it at 600px to the count that suits
   their own number of tiles (3 and 2), and historial_entrenos.php reads
   fine at 3. Overriding it from here only made those choices worse. It IS
   handled in the tablet band above, where none of those queries reach. */
.chart-hdr { flex-wrap:wrap; gap:8px; }
.dias-filter { flex-wrap:wrap; }
.dias-filter a {
    min-height:38px; display:inline-flex; align-items:center;
    padding:8px 13px; font-size:12px;
}
/* rendimiento_atleta.php: the four periods share the row with their label
   in equal parts instead of wrapping one of them onto a line of its own. */
.page-actions .dias-filter { flex:1 1 auto; flex-wrap:nowrap; }
.page-actions .dias-filter a { flex:1 1 0; justify-content:center; padding:8px 6px; }
.w-table { min-width:560px; }
.hoy-sin { flex-wrap:wrap; }
/* bienestar_atleta.php, today's card: the badge and the score share the top
   line and the five answers take the full width under them, instead of
   stacking one per line in the gap between the two. */
.hoy-card { gap:12px; padding:14px 16px; }
.hoy-vals { order:3; flex:1 1 100%; }
.atl-item { padding:12px 14px; }

/* ── historial_entrenos.php ────────────────────────────────────────
   The log header reserved ~271px for the date box, five wellness dots and
   a chevron, leaving about 70px for the routine name. */
.log-head { flex-wrap:wrap; gap:10px; padding:12px 14px; }
.log-info { flex:1 1 55%; }
.log-w { flex-wrap:wrap; }
.log-body { padding:12px; }

/* historial_entrenos.php · rendimiento_atleta.php: the summary tiles put
   an icon beside the number, and three or two of them across a phone left
   the number about 60px. The icon goes on top instead. */
.hist-center .stat-card, .rd-center .stat-card {
    flex-direction:column; align-items:flex-start; gap:10px; padding:14px;
}
.hist-center .stat-icon, .rd-center .stat-icon {
    width:34px; height:34px; font-size:14px; border-radius:10px;
}
.hist-center .stat-num, .rd-center .stat-num { font-size:22px; }

/* ── evaluacion_nueva.php ──────────────────────────────────────────
   The segment table's wrapper never scrolled because the table was
   width:100% with no floor, so four control columns shared 340px. */
.ev-layout { grid-template-columns:1fr; }
.ev-preview { position:static; max-height:none; }
.ev-sec-head { flex-wrap:wrap; gap:10px; }
.ev-sec-head .accion { margin-left:0; }
.seg-table { min-width:620px; }
.seg-table input, .seg-table select { font-size:16px; min-height:40px; }
.form-actions { flex-wrap:wrap; gap:8px; padding:12px 14px; }
.form-actions a, .form-actions button { flex:1 1 auto; justify-content:center; }
.ic-ejercicio { grid-template-columns:1fr; }

/* ── ejercicios.php ────────────────────────────────────────────────
   The image inside the view modal is pulled out to the modal's own edges
   with a negative margin sized for the desktop padding of 26px. */
.ver-img { margin:-20px -16px 16px -16px !important; }
.clasif-opt { min-height:38px; }
.filters { gap:8px; }
/* Asignaciones: the add form takes a full line under the coaches. */
.as-fila { gap:10px; }
.as-agregar { flex:1 1 100%; margin-left:0; flex-wrap:wrap; }
.as-agregar .form-select { flex:1 1 100%; min-width:0; }
/* Master-file import: four counters do not fit a phone's width in a row. */
.em-resumen { grid-template-columns:repeat(2,1fr); }
.em-pie { flex-direction:column-reverse; }
.em-pie .btn-primary, .em-pie .btn-secondary { width:100%; justify-content:center; }

/* ── detalle_ejercicio.php ─────────────────────────────────────────
   Four tabs on one non-wrapping row need about 460px, so the fourth sat
   off-screen. They scroll sideways instead, which keeps the tab metaphor. */
.tabs {
    overflow-x:auto; -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
}
.tabs::-webkit-scrollbar { display:none; }
.tab { flex-shrink:0; min-height:42px; padding:10px 15px; }
.chart-filters { flex-wrap:wrap; gap:6px; }
.cf-btn { min-height:36px; display:inline-flex; align-items:center; padding:7px 12px; }
.info-row { flex-wrap:wrap; }
.info-lbl { min-width:0; flex:1 1 100%; }
.hist-tbl { min-width:540px; }

/* ── rutinas.php — the session builder ─────────────────────────────
   The heaviest screen in the app. Two of its grids are wider than a phone
   on their own: the exercise picker (190+230+170 plus a free column, ~590px
   minimum) and the set editor (nine tracks, ~457px minimum). */
.ent-layout { flex-direction:column; min-height:0; }
.ent-center { padding:14px 12px; overflow:visible; }
.vt-row { gap:10px; }
.vt-acciones { margin-left:0; width:100%; }
.vt-acciones > * { flex:1 1 auto; justify-content:center; }
.gc-grid { grid-template-columns:1fr; }
.fsec-body { padding:14px; }
/* The save bar above the form: full width, like every other button here. */
.acciones-top .btn-primary { flex:1 1 100%; }
.dias-wrap { gap:6px; }
.dia-lbl { min-height:40px; display:inline-flex; align-items:center; padding:8px 14px; }
.w-mini { min-width:46px; padding:6px 8px; }
/* "Mis sesiones", a week at a time: the week and its arrows keep the first
   row, "Hoy" and "Calendario" share the second, and the athlete select —
   standing in for the athlete panel, which is hidden here — takes the third.
   The calendar spans the bar instead of hanging off its right edge. */
.sw { padding:12px; }
.sw-flecha { width:40px; }
.sw-flecha, .sw-hoy, .sw-cal-btn, .sw-volver { height:40px; }
.sw-titulo { flex:1 1 calc(100% - 104px); min-width:0; }
.sw-hoy, .sw-cal-btn { flex:1 1 0; margin-left:0; }
.sw-atl { display:flex; align-items:center; gap:8px; flex:1 1 100%; height:40px; padding:0 11px;
    border:1px solid var(--border); border-radius:8px; background:#fff; color:var(--muted); font-size:11px; }
.sw-atl select { flex:1; min-width:0; border:0; outline:0; background:transparent; font-family:'Inter',sans-serif;
    font-size:13px; font-weight:600; color:var(--text); }
.sw-cal { left:0; right:0; width:auto; }
.sw-dias { gap:4px; }
.sw-dia b { font-size:14px; }
.sw-est { min-height:34px; }
.sw-sel { margin-left:0; flex-basis:100%; }
/* The tray's explanation drops under its title, the chevron stays on the right. */
.sw-bandeja summary span { flex-basis:100%; order:1; min-width:0; }
.sw-bandeja summary .fa-chevron-down { margin-left:auto; }
/* The session's date field takes the width under the weekday chips, and its
   calendar opens across it. */
.fecha-ses { max-width:none; }
.fecha-campo { height:44px; }
.cal-pop { left:0; right:0; width:auto; max-width:none; }
.cal-ses-d { height:36px; }

/* The set editor and the exercise picker are handled in their own media
   query below (they need to fold on a tablet in portrait too). */

/* The bulk-import modal's result table is six columns inside a box whose
   overflow:hidden cancelled the horizontal scroll it needed. */
.im-res { overflow:auto !important; }
.im-res table { min-width:560px; }
.im-hd, .im-bd, .im-ft { padding-left:16px; padding-right:16px; }
.im-ft {
    flex-wrap:wrap; gap:8px;
    padding-bottom:calc(16px + env(safe-area-inset-bottom));
}
.im-ft > * { flex:1 1 100%; justify-content:center; }

/* historial_entrenos.php — the export dialog's two-column form. */
.exp-grid { grid-template-columns:1fr; }
.exp-grid > * { grid-column:auto !important; }
.exp-acc { flex-wrap:wrap; }
.exp-acc > * { flex:1 1 100%; justify-content:center; }

/* The methods panel: a two-column form inside a modal that is already down to
   16px of padding leaves each field about 120px wide. */
.met-adm-grid { grid-template-columns:1fr; }
.met-adm-grid > * { grid-column:auto !important; }
.met-adm-acc { flex-wrap:wrap; }
.met-adm-acc > * { flex:1 1 100%; justify-content:center; }
.met-adm-fila { flex-wrap:wrap; }
.met-adm-acciones { width:100%; justify-content:flex-end; }
.met-adm-btn { width:38px; height:38px; }

/* An absolutely positioned dropdown 420px tall does not fit above the fold
   on a phone when it opens near the bottom of the form. */
.obj-opts { max-height:52dvh; }
.ej-nm-lista { max-height:44dvh; }

/* Session list actions. */
.vtb, .htb { min-height:38px; display:inline-flex; align-items:center; }

} /* end 3 */


/* ═══════════════════════════════════════════════════════════════════
   4. PHONE — athlete portal
   This is the half of the app that is actually used on a phone, and the
   only one with no sidebar: it carries its whole theme inline and never
   loads main.css.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:768px) {

/* The tab bar scrolls sideways with its scrollbar hidden, so the fourth tab
   sat half off-screen with nothing to say it was there. Four tabs fit once
   they stop reserving desktop padding. */
.nav-portal { padding:0 4px; }
.nav-item, .nav-it { padding:11px 8px; font-size:11.5px; gap:4px; }

/* The session title is a flex child with no floor and no ellipsis, inside a
   58px bar that cannot grow: a long name spilled out of the bar. */
.tb-title {
    min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    font-size:14px;
}
.back-btn { min-height:40px; padding:0 4px; }

/* The three-step indicator needs ~400px as written, so it scrolled the whole
   page sideways on every phone. Same shape, smaller parts. */
.steps { padding:16px 10px 0; }
.step { font-size:10.5px; gap:5px; }
.step-circle { width:24px; height:24px; font-size:10px; }
.step-line { width:14px; margin:0 3px; }

/* Wellness rows: an emoji, a label and five buttons on one line. The longer
   labels ("Dolor/Molestias", "Motivación") pushed the fifth button past the
   right edge, and where they did not, they squeezed the buttons to 24px.
   The buttons keep their size and take their own line when needed. */
.w-row { flex-wrap:wrap; gap:10px 12px; padding:12px 14px; }
.w-label { flex:1 1 auto; min-width:0; }
.w-stars, .stars { flex-wrap:wrap; margin-left:auto; gap:6px; }
.w-star, .star-btn {
    flex-shrink:0;
    width:42px; height:42px; min-height:42px; font-size:15px;
}

/* Set logging — the thing the athlete touches mid-set, one-handed.
   The row is a five-track grid whose comment field asks for columns 2-5;
   with the fields already filling row one, auto-placement pushed the
   comment AND the delete button onto row two, leaving the delete button
   beside the comment and a 22px column empty on row one. Placing every
   cell explicitly removes the guesswork.

   The tick that marks the set done takes the last column of the first row,
   beside the numbers it confirms, at the full height of the inputs: it is
   the one control pressed on every set. Deleting a set is rare, so its
   button moves down to the comment's line, out of the way of the tick. */
.sets-hdr, .set-row { grid-template-columns:24px 1fr 1fr 1fr 44px; column-gap:5px; }
.set-row > * { min-width:0; }
.set-row .set-idx        { grid-column:1; grid-row:1; }
.set-row .campo-reps     { grid-column:2; grid-row:1; }
.set-row .campo-peso     { grid-column:3; grid-row:1; }
.set-row .campo-rir      { grid-column:4; grid-row:1; }
.set-row .btn-check      { grid-column:5; grid-row:1; }
.set-row .btn-rm-set     { grid-column:5; grid-row:3; justify-self:center; }
.set-row .set-nota-coach { grid-column:1 / -1; grid-row:2; }
.set-row .row-nota       { grid-column:1 / 5; grid-row:3; }
.set-row .set-plan       { grid-column:1 / -1; grid-row:4; }
/* The space between the stacked rows is each cell's own margin rather than the
   grid's row-gap: only a set the coach left a note on has a row 2, and a gap
   would have charged every other set for the empty track all the same. */
.set-row { row-gap:0; }
.set-row .set-nota-coach,
.set-row .row-nota,
.set-row .btn-rm-set,
.set-row .set-plan { margin-top:5px; }

/* The coach's instruction for this set, on the line it applies to and directly
   above the box where the athlete answers it. Said once in the group heading,
   it had scrolled off the top by the third set of a long prescription — which
   is where the athlete is when they need to read it. The heading's copy goes,
   so the sentence is not printed twice on a screen this narrow. */
.sg-nota { display:none; }
.set-nota-coach {
    display:block;
    font-size:11px; line-height:1.35;
    color:var(--primary); opacity:.85;
}

/* Every field says what it is, on its own line.
   A card can hold a dozen sets, so the column header is off the top of the
   screen for most of the ones the athlete is actually typing into — three bare
   numbers with nothing saying which is reps, which is weight and which is RPE.
   The wrapper is `display:contents` on a wide screen (portal/entrenamiento.php),
   so this is the only place where it becomes a box; the grid columns are the
   same ones, now occupied by the label instead of the input it holds.

   The header is what the row replaced, so it goes: kept, it repeated the same
   three words directly above the first row and cost a line of a screen the
   athlete reads mid-set. The asterisk that marked reps and weight as required
   moves into the labels rather than being lost with it. */
.sets-hdr { display:none; }
.set-campo { display:flex; flex-direction:column; gap:3px; min-width:0; }
.set-campo > span {
    display:block;
    font-size:9.5px; font-weight:700; letter-spacing:.4px;
    text-transform:uppercase; color:var(--muted); text-align:center;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* The number column has no label above it, so its digit lines up with the
   inputs rather than with the words naming them. */
.set-row { align-items:end; }
.set-row .set-idx { padding-bottom:12px; }
/* A line logged in pounds carries the kilograms it comes to under its weight
   field, which makes that cell 15px taller than the two beside it. The row is
   bottom-aligned, so without this the three fields would sit on three
   different lines. The reserved space goes under the neighbours instead. */
.set-row:has(.row-kg-eq:not([hidden])) .campo-reps,
.set-row:has(.row-kg-eq:not([hidden])) .campo-rir { padding-bottom:15px; }
.set-row:has(.row-kg-eq:not([hidden])) .set-idx { padding-bottom:27px; }

.set-row input, .ej-notas input, .final-field input, .final-field textarea {
    font-size:16px; min-height:44px;
}
.row-nota { font-size:14px; min-height:40px; padding:8px 10px; }
.btn-rm-set {
    width:34px; height:34px; font-size:20px;
}
.btn-check { width:44px; height:44px; font-size:16px; }
.btn-add-serie { min-height:42px; }
.ej-indica-toggle { min-height:34px; padding:4px 0; }
/* Label, name and plan, the ticked count and the fold button on one line:
   the name's block takes what is left and wraps inside itself. */
.ej-head { gap:8px; padding:12px 14px; }
.ej-nombre { overflow-wrap:anywhere; }
.ej-body { padding:12px 14px; }
/* The ten difficulty buttons share the row in equal parts. The fixed 42px
   width above is for rows of five; ten of those are wider than a phone. */
.w-stars.diez .w-star { width:auto; height:40px; min-height:40px; font-size:14px; }
.resumen { gap:8px; }
.res-val { font-size:16px; }
/* Five arrival tiles across a phone: about 60px each, which holds the emoji,
   a short label and the score once the padding and the number shrink. */
.llegada { gap:6px; }
.lleg-item { padding:10px 3px 9px; }
.lleg-lbl { font-size:9px; letter-spacing:.2px; }
.lleg-val { font-size:19px; }
.bl-head { padding:10px 12px; }
.bloque { padding-left:10px; }
.hoja-fondo { padding:12px 12px calc(12px + env(safe-area-inset-bottom)); }
.final-row { grid-template-columns:1fr; }

/* The pinned action bar sat under the home indicator on notched phones, and
   had no stacking context of its own. */
.bottom-bar {
    z-index:60;
    padding:12px 16px calc(12px + env(safe-area-inset-bottom));
}
.btn-next, .btn-finish, .btn-back-step { min-height:48px; }

/* Planned-vs-actual comparison: three columns of ~93px holding values like
   "4×10,10,8,8 45kg" that have no break opportunity in them. */
.cmp-row, .cmp-head { gap:6px; }
.cmp-ej, .cmp-plan, .cmp-real { min-width:0; overflow-wrap:anywhere; }

/* Session cards. */
.ses-header { flex-wrap:wrap; }
.ses-actions { flex-wrap:wrap; gap:8px; width:100%; }
.ses-actions > * { flex:1 1 auto; justify-content:center; min-height:42px; }
.ej-row { flex-wrap:wrap; }
.ej-data { min-width:0; }
/* An 80px left inset left ~178px of text on a small phone. */
.ej-indica-wrap { padding:0 16px 10px 16px; }
.ej-indica-btn { min-height:32px; }

/* Month navigation in the athlete's history: the ‹ › arrows are the most
   tapped control on the page and were 35×32px. */
.month-nav { flex-wrap:wrap; gap:8px; }
.nav-btn {
    min-height:42px; min-width:48px;
    display:inline-flex; align-items:center; justify-content:center;
}
.toggle-btn { min-height:34px; }
.tback, .logout, .logout-btn, .btn-start, .btn-outline, .btn-iniciar, .btn-expandir {
    min-height:40px; display:inline-flex; align-items:center; justify-content:center;
}

/* feedback.php has the most generous padding in the portal and no media
   query at all, which is what squeezed its five rating buttons to 26px. */
.w-item { flex-wrap:wrap; gap:10px 12px; }

} /* end 4 */

/* The portal's tab bar holds five tabs since Mensajes joined it. At phone
   width the five labels fit only without their icons; kept, the fifth tab
   sat half off-screen behind a scrollbar nobody can see. The bell in the
   topbar is the other way to the chat. */
@media (max-width:420px) {
    .nav-portal .nav-it i, .nav-portal .nav-item i { display:none; }
    .nav-portal .nav-it, .nav-portal .nav-item { padding:11px 7px; }
    .msg-campana { width:34px; height:34px; }
}


/* ═══════════════════════════════════════════════════════════════════
   5. LOGIN SCREEN
   The scrolling half of this — a panel taller than the screen whose top
   edge could not be reached — is fixed in login.php itself, because the
   rules involved (`body{overflow}`, `align-items`) are not login-specific
   selectors and would reach every other page from here. What is left is
   the touch sizing, which is.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:900px) {
    /* Show/hide password was a 17x14px hit area. */
    .eye-btn {
        width:40px; height:40px;
        display:flex; align-items:center; justify-content:center;
        right:6px;
    }
    .chk-wrap { min-height:40px; display:flex; align-items:center; }
    /* iOS zooms into anything under 16px and never zooms back out. */
    .fwrap input { font-size:16px; }
}


/* ═══════════════════════════════════════════════════════════════════
   6. NARROW PHONE — 420px and below (iPhone SE, older Androids)
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:359px) {
    .stats-grid { grid-template-columns:1fr; }
}

/* Wellness ratings, phone-width: the label ("Dolor/Molestias") and five
   42px buttons cannot share a line under about 480px, and once the buttons
   wrap, the margin-left:auto that right-aligned them leaves a ragged gap.
   Below this width they always take their own line and spread across it,
   which is both predictable and easier to hit. */
@media (max-width:480px) {
    .w-row .w-stars,
    .w-item .stars {
        flex:1 1 100%; margin-left:0; justify-content:space-between; gap:6px;
    }
    .w-star, .star-btn { flex:1 1 0; max-width:60px; }
}

@media (max-width:420px) {

.content { padding:14px 12px; }
.page-header h1 { font-size:17px; }

/* Two buttons sharing a modal footer stop fitting their own labels here
   ("Crear entrenador" wrapped to two lines inside its button). Stack them,
   primary action on top, the way the shared confirm dialog already does. */
.modal > form > div[style*="display:flex"],
.modal > div[style*="display:flex"] { flex-wrap:wrap; }
.modal > form > div[style*="display:flex"] > *,
.modal > div[style*="display:flex"] > * { flex:1 1 100% !important; }

/* Two full buttons side by side stop fitting their own labels here. Only
   buttons: .page-actions also holds short filter chips (7D/14D/30D/90D),
   and one row each for those is absurd. */
.page-header .ph-actions > .btn-primary,
.page-header .ph-actions > .btn-secondary,
.page-actions > .btn-primary,
.page-actions > .btn-secondary { flex:1 1 100%; justify-content:center; }

.cal-dow { font-size:8.5px; padding:6px 1px; }
.cal-day { min-height:54px; }
.day-num { width:20px; height:20px; font-size:11px; }

/* Portal: the card and page padding together were eating 100px of the
   width before any content was drawn. */
.card, .wellness-card { padding:18px 14px; }
.ej-body { padding:12px 12px; }
.sets-seccion { padding:8px; }
.serie-grupo { padding:6px 8px 4px; }

} /* end 6 */


/* ═══════════════════════════════════════════════════════════════════
   7. RUTINAS — THE SET EDITOR AND THE EXERCISE PICKER
   These two grids are wider than the space they get long before the
   sidebar goes away, so they need a band of their own. With the 260px
   sidebar and the 210px athlete rail still in place, a 820px tablet
   leaves the session builder about 310px to work with.
   ═══════════════════════════════════════════════════════════════════ */

/* Exercise picker. It is a filter bar over two columns now, and rutinas.css
   already stacks those two under 900px; what is left for a phone is the
   16px minimum that stops iOS zooming into a field on focus, and the bar's
   controls going full width instead of queueing up in a cramped row. */
@media (max-width:768px) {
    .ej-filtros-bar { gap:8px; }
    .ej-filtros-bar select { flex:1 1 100%; font-size:16px; min-height:44px; }
    .ejb-buscar { flex:1 1 100%; }
    .ejb-buscar input { font-size:16px; min-height:30px; }
    .ejb-link { flex:1 1 100%; }
    /* The row's actions sit beside a name that can be long: let them wrap
       under it rather than squeezing the name to nothing. */
    .ej-item { flex-wrap:wrap; }
    .ej-item-acc { margin-left:auto; }
    .ej-add, .ej-add-s { min-height:44px; padding-inline:16px; }
}

@media (max-width:900px) {
/* Set editor. Ten tracks — #, Aprox., Series, Reps, Peso, Desc., RPE, RIR,
   Notas, delete — needing about 490px before they can even start to shrink,
   against roughly 300px of usable width. Rather than crush all ten to
   ~25px each, the row folds into two lines: what you prescribe first on
   top (series, reps, weight), the qualifiers underneath.

       [ #  ][ Series ][ Reps  ][ Peso ][ x  ]
       [APR ][ Desc.  ][ RPE   ][Notas ][RIR ]

   RIR rides in the narrow last track because it is never more than one digit
   and is never typed into: it is the RPE beside it, said the other way up.

   Every cell is placed by hand because the two grids hold ten children in
   a fixed source order and auto-placement would scatter them. The header
   row folds the same way, so its labels stay over their fields. */
.ej-set-labels,
.ej-set-row {
    /* Weight gets the widest track: it is the only field that regularly
       carries four digits and two decimals ("142,00"). */
    grid-template-columns:34px 1fr 1fr 1.35fr 34px;
    gap:5px;
    align-items:center;
}
.ej-set-row { padding:9px 10px; border-bottom:1px solid var(--border); }
.ej-set-row:last-child { border-bottom:none; }
.ej-set-labels { padding:6px 10px 4px; }
.ej-set-labels > *, .ej-set-row > * { min-width:0; }

/* Top line */
.ej-set-labels > :nth-child(1),
.ej-set-row > .ej-set-idx                   { grid-area:1 / 1; }
.ej-set-labels > :nth-child(3),
.ej-set-row > input[name^="ej_series"]      { grid-area:1 / 2; }
.ej-set-labels > :nth-child(4),
.ej-set-row > input[name^="ej_reps"]        { grid-area:1 / 3; }
.ej-set-labels > :nth-child(5),
.ej-set-row > input[name^="ej_peso"]        { grid-area:1 / 4; }
.ej-set-labels > :nth-child(10),
.ej-set-row > .btn-rmset                    { grid-area:1 / 5; }

/* Second line */
.ej-set-labels > :nth-child(2),
.ej-set-row > .aprox-tog                    { grid-area:2 / 1; }
.ej-set-labels > :nth-child(6),
.ej-set-row > input[name^="ej_descanso"]    { grid-area:2 / 2; }
.ej-set-labels > :nth-child(7),
.ej-set-row > input[name^="ej_rpe"]         { grid-area:2 / 3; }
.ej-set-labels > :nth-child(9),
.ej-set-row > input[name^="ej_notas"]       { grid-area:2 / 4; }
.ej-set-labels > :nth-child(8),
.ej-set-row > .ej-rir-celda                 { grid-area:2 / 5; }

.ej-set-labels > span {
    font-size:9.5px; text-align:center;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.ej-set-row input { padding:9px 4px; font-size:16px; min-height:42px; text-align:center; }
.ej-set-row input[name^="ej_notas"] { text-align:left; padding-left:9px; }

/* The exercise name shares its row with a catalogue badge, a group chip
   and a delete button; on a phone it was cut to five characters rather
   than given a line of its own. */
.ej-block-hdr { flex-wrap:wrap; gap:8px 6px; }
.ej-block-hdr .ej-nm-wrap { flex:1 1 100%; order:-1; }
.ej-block-hdr .ej-fnm { font-size:14px; }
.btn-rmset, .btn-rmblock {
    width:32px; height:32px; min-height:32px;
    display:flex; align-items:center; justify-content:center;
}
.btn-addset { min-height:38px; padding:8px 14px; }
.aprox-tog span { min-height:32px; display:inline-flex; align-items:center; }
}


/* ═══════════════════════════════════════════════════════════════════
   8. HISTORIAL — THE EXERCISES OF ONE SESSION
   historial_entrenos.php lays each exercise out as a seven-column row
   (name, planned, actual, weight delta, volume, RPE, done). With the
   sidebar and the 240px athlete rail still in place, a 1024px screen
   leaves that row about 440px, so from 1100px down each exercise
   becomes a small card: the name across the top, then the figures in
   a 3-column grid, each carrying its own label.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:1100px) {
    .ej-cab { display:none; }
    .ej-fila {
        grid-template-columns:repeat(3, minmax(0, 1fr));
        gap:12px 10px; padding:12px; align-items:start;
    }
    .ej-c-nm, .ej-c-ok { align-self:center; }
    .ej-fila:nth-child(2) { border-top:none; }
    /* Placed by hand: what was prescribed and what was done read first,
       side by side with the volume; the weight delta and RPE below. */
    .ej-c-nm  { grid-area:1 / 1 / 2 / 3; }
    .ej-c-ok  { grid-area:1 / 3; justify-self:end; }
    .ej-c-pl  { grid-area:2 / 1; }
    .ej-c-re  { grid-area:2 / 2; }
    .ej-c-vol { grid-area:2 / 3; }
    .ej-c-dp  { grid-area:3 / 1; }
    .ej-c-rpe { grid-area:3 / 2; }
    .ej-notas { grid-row:4; }
    .ej-c-dp, .ej-c-vol, .ej-c-rpe { text-align:left; }
    .ej-c[data-lbl]::before {
        content:attr(data-lbl); display:block; margin-bottom:3px;
        font-size:9px; font-weight:700; color:var(--muted);
        text-transform:uppercase; letter-spacing:.4px;
    }
    .ej-notas { margin-left:0; }
    /* The name has the card's whole top line now; let it take two. */
    .ej-nm { white-space:normal; }
}


/* ═══════════════════════════════════════════════════════════════════
   9. DETALLE DEL EJERCICIO — the hero and the card headers
   detalle_ejercicio.php puts three figures beside the exercise name, and
   the chart cards carry four period buttons beside their title. With the
   sidebar in place, from 1100px down the name was left about 130px, so
   the figures drop to a row of their own under it and the buttons to a
   line under their title.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:1100px) {
    .ej-hero { flex-wrap:wrap; }
    .ej-hero-cifras { flex:1 1 100%; flex-wrap:wrap; padding:0 20px 20px; }
    .ej-hero-cifras .hc { flex:1 1 100px; }
    .det-card-hdr { flex-wrap:wrap; }
    .det-card-hdr .chart-filters { flex:1 1 100%; }
}


/* ═══════════════════════════════════════════════════════════════════
   10. FUERTE Y DÉBIL POR GRUPO MUSCULAR — the athlete cards
   includes/musculos.php lays the cards out as an auto-fit grid, so they
   reflow on their own down to the 340px track; what does NOT reflow is
   what is inside one. The verdict is two columns side by side, and on a
   phone each of them is left about 150px — enough for "Isquiotibiales"
   only by breaking it across three lines. Below 768px the two stack, the
   track floor is dropped so a 360px screen gets no horizontal scroll, and
   the evidence table scrolls in its own box instead of squeezing five
   columns into the card.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width:768px) {
    .mus-rejilla { grid-template-columns:1fr; }
    .mus-ver     { grid-template-columns:1fr; }
    .mus-cab p   { font-size:12px; }
    /* The group name is the answer; let it keep the width it needs. */
    .mus-v-grupo { font-size:15px; }
    .mus-barras li { grid-template-columns:minmax(64px,34%) 1fr auto; }
    /* Five columns of numbers do not fit; the box scrolls, the card does not. */
    .mus-tabla-caja { overflow-x:auto; }
    .mus-tabla { min-width:300px; }
}
