/* ============================================================================
   US OPEN 2026 — MATCH ROW, styles
   ============================================================================
   ONE row, used by the matches page and by a player's route on their profile.
   It was written for the matches page and then wanted on the profile, where
   the honest options were to copy it or to share it. Copied, the two drift
   within a week — the guidelines say so because it has already happened to
   this component's sibling, the match panel.

   Paired with 02. data/uso-match-row.js, which owns the markup. The class
   names below are the contract between the two.

   The profile passes a round chip (R1, QF) through opts; the matches page
   does not, because there the round is a heading above the group.
   ========================================================================== */

/* ── The row ──────────────────────────────────────────────────────────────
   Two player lines, same shape as the bracket card, so a match reads
   identically wherever it appears. */
.mrow{display:flex;flex-direction:column;background:rgba(255,255,255,.04);
 border:1px solid var(--line);border-left:3px solid rgba(255,255,255,.16);
 border-radius:10px;overflow:hidden;transition:.14s;}
/* What .mrow used to be. The two players and the meta column still sit side
   by side; they are just no longer the whole row. */
.m-top{display:flex;align-items:stretch;gap:0;}
.mrow.final{border-left-color:var(--gold);}
.mrow.live{border-left-color:var(--red);border-color:rgba(224,20,43,.5);}
.mrow:hover{background:rgba(255,255,255,.07);}
/* The row opens the match panel now, so it says so: a hover that lifts rather
   than just tints, and a real focus ring for the keyboard. The names inside
   keep their own gold hover — two targets, two signals, no ambiguity. */
.mrow[data-mid]:hover{border-color:rgba(231,198,107,.38);}
/* ⚠️ ASYMMETRIC ON PURPOSE — 8px in, 14px out. The seed column is 26px of
   reserved space that is right-aligned, so a one-digit seed already sits about
   18px from its own left edge. Add 14px of padding on top and a "3" was
   floating a third of the way across the row with nothing beside it, while the
   names it should have been leading were ellipsing on a phone. The gap the eye
   sees is padding PLUS the empty half of the slot; only the padding is ours to
   spend, so it goes to the names. */
.m-body{flex:1;min-width:0;padding:9px 14px 9px 8px;}
.m-side{display:flex;align-items:center;gap:9px;padding:3px 0;min-width:0;}
.m-side + .m-side{border-top:1px solid rgba(255,255,255,.07);}
/* ── SEED / RANKING SLOT ───────────────────────────────────────────────────
   ONE WIDTH FOR EVERY VALUE, sized for the widest thing it can hold — "#412".
   A one-digit seed gets the same 26px as a three-digit ranking, so the flag
   column beside it starts on the same vertical line down the whole list and
   nothing shuffles as the rounds thin out and the seeds drop away.

   RIGHT-ALIGNED so values grow leftward into their own reserved space. Centred,
   a "1" and a "#412" put their ink in different places relative to the flag
   next to them, and the two lines of a single match looked out of register
   with each other even though the columns were identical. */
.m-seed{flex:none;width:26px;text-align:right;font-size:10px;font-weight:900;
 color:var(--gold);font-variant-numeric:tabular-nums;}
.m-seed.none{color:var(--soft);opacity:.45;font-weight:700;}
/* The ranking, when there is no seed. SAME SIZE AND WEIGHT AS THE SEED — they
   are the same kind of fact in the same column, and setting the ranking
   smaller made the two lines of one match look like a heading and a footnote.
   Colour and the hash carry the difference, which is enough: gold means seeded
   everywhere on this site, and nothing else here is prefixed with #. */
.m-seed.rank{color:var(--soft);letter-spacing:-.02em;}
.m-name{flex:1;min-width:0;font-size:15px;font-weight:700;color:var(--mut);
 overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.m-side.win .m-name{color:#fff;font-weight:900;}
.nm-short{display:none;}
/* ⚠️ SPECIFICITY, and it swallowed the hover on exactly the name you most
   want to click. `.m-side.win .m-name` above is (0,3,0); a bare
   `.m-name:hover` is (0,2,0), so the winner's white beat the gold and only
   the LOSER's name lit up. Nothing looked broken — half the names worked,
   which reads as a design choice rather than a bug.
   Matching the winner's selector and adding :hover takes this to (0,4,0), so
   every player name on the page golds on rollover, won or lost. */
.m-name:hover,
.m-side.win .m-name:hover{color:var(--gold);}
/* ⚠️ THE 5px ON THE RIGHT IS THE GAP TO THE NAME, and it is here rather than
   on .m-side's gap because only this edge needs it: the seed sits happily
   close to the flag, the name did not. On a phone the country letters are
   hidden and the flag is 16px, so without this the name butted straight up
   against it. */
.m-ctry{flex:none;width:44px;margin-right:5px;display:inline-flex;align-items:center;
 font-size:9px;font-weight:800;letter-spacing:.06em;color:var(--soft);}
/* Flag + code. The flag is decorative and the letters carry the meaning, so
   an unmapped country degrades to letters alone rather than a broken image.
   Fixed width stops the row jumping as flags load one by one. */
.flag{display:inline-block;width:16px;height:11px;object-fit:cover;border-radius:2px;
 vertical-align:-1px;margin-right:4px;background:rgba(255,255,255,.08);flex:none;}

.m-sets{flex:none;display:flex;gap:3px;}
.m-sets i{display:block;width:14px;text-align:center;font-style:normal;
 font-size:13px;font-weight:800;color:var(--soft);font-variant-numeric:tabular-nums;}
.m-side.win .m-sets i{color:var(--gold);}
/* Provisional last set — the match is over but the result has not published,
   so this is the last score the live feed sent rather than the final one.
   Dotted underline, matching the home card; the panel uses a dashed box
   because it has a box to dash. */
.m-sets i.pend{text-decoration:underline dotted;text-underline-offset:2px;opacity:.7;}

/* ── The live point ────────────────────────────────────────────────────────
   0 / 15 / 30 / 40 / AD — the only number on the row that changes while you
   are looking at it, so it gets the box.

   Fixed width, not padding: "AD" is two characters and "0" is one, and a box
   that resized every point would jiggle the whole column on every rally. */
.m-pt{flex:none;width:32px;text-align:center;font-size:12px;font-weight:900;
 font-variant-numeric:tabular-nums;color:var(--gold);
 background:rgba(231,198,107,.16);border:1px solid rgba(231,198,107,.38);
 border-radius:6px;padding:3px 0;line-height:1.15;}

/* Serving. A point score without knowing who is serving is half a fact — it is
   the difference between 40-30 being comfortable and being a break point. */
.m-pt.srv{background:var(--gold);color:#0a1c38;border-color:var(--gold);}

/* Break point: the receiver is one point from taking serve. Rare, pivotal, and
   the moment a match turns — the one thing on this page worth interrupting the
   palette for. Derived by situation() in uso-live.js, not sent by the feed. */
.m-pt.bp{background:var(--red);border-color:var(--red);color:#fff;}

/* ── The point box moves while the point is live ───────────────────────────
   The serving box is the one thing on the row that is TRUE RIGHT NOW — that
   player is standing at the baseline about to hit. Solid gold said so; a
   pulsing solid gold says it is happening.

   Three speeds, deliberately ranked, because everything moving at one speed
   is just noise:
     break point  1.2s — the most urgent thing in tennis
     serving      2.2s — steady, a heartbeat rather than an alarm
     LIVE pill    1.5s — the page-level "this is connected"

   The glow rides on box-shadow, never opacity or scale: the number inside has
   to stay readable at every frame, and a box that changes size would nudge the
   whole row on every cycle.

   STAGGERED. With a dozen live matches on screen, one shared timing makes the
   page blink like a machine. A few hundred milliseconds of offset per row and
   it reads like a dozen separate matches happening at once — which is what it
   actually is. */
@keyframes servePulse{
 0%  {box-shadow:0 0 0 0 rgba(231,198,107,.85);}
 55% {box-shadow:0 0 0 8px rgba(231,198,107,0);}
 100%{box-shadow:0 0 0 0 rgba(231,198,107,0);}
}
@keyframes bpPulse{
 0%  {box-shadow:0 0 0 0 rgba(224,20,43,.95);}
 55% {box-shadow:0 0 0 9px rgba(224,20,43,0);}
 100%{box-shadow:0 0 0 0 rgba(224,20,43,0);}
}
.m-pt.srv{animation:servePulse 2.2s ease-out infinite;}
.m-pt.bp {animation:bpPulse   1.2s ease-out infinite;}
/* Stale outranks both — a score that is not current must not look busy. */
.m-pt.stale{animation:none;}

.mrow:nth-child(4n+2) .m-pt{animation-delay:.45s;}
.mrow:nth-child(4n+3) .m-pt{animation-delay:.9s;}
.mrow:nth-child(4n+4) .m-pt{animation-delay:1.35s;}

@media(prefers-reduced-motion:reduce){
 .m-pt.srv,.m-pt.bp{animation:none;}
}

/* The provider telling us ITS data has gone quiet — a suspension, a feed drop,
   rain. The number on screen is no longer current, so it stops looking live
   rather than continuing to present a frozen score as the truth. */
.m-pt.stale{opacity:.45;background:transparent;color:var(--soft);
 border-color:var(--soft);border-style:dashed;}

/* A tiebreak counts POINTS, not games — first to seven, win by two. Same box,
   but the numbers mean something different, so they are marked. */
.m-pt.tb::after{content:"TB";display:block;font-size:6.5px;letter-spacing:.08em;
 opacity:.75;margin-top:-1px;}
/* Sized for a date, not for a tag. This column was 92px wide to hold the
   "Final" pill; with that gone it only ever carries a date, so the leftover
   width goes to the names instead. It disappears entirely when it has
   nothing in it — an empty panel with a divider reads as a missing value. */
.m-meta{flex:none;width:90px;display:flex;flex-direction:column;align-items:center;
 justify-content:center;gap:3px;padding:8px 6px;border-left:1px solid var(--line);
 background:rgba(6,18,42,.35);}
/* No longer ever empty — every row carries the details button now — but kept
   in case a row is ever built without one. */
.m-meta:empty{display:none;}
/* ── "View match details" ─────────────────────────────────────────────────
   A band across the foot of the row, the full width of a five-set scoreline.

   ── THE WORDING HAS TO SURVIVE ALL THREE TENSES ──────────────────────────
   The same row appears for a match that finished on Sunday, one on court now
   and one that starts on Thursday. "View match" reads like an invitation to
   watch it, which is a promise this site cannot keep for any of the three.
   "View match details" is what is actually behind the band in every case:
   the players, the record, and whatever score exists yet.

   State-specific labels — "View result", "Watch live", "View preview" — were
   the obvious alternative and are worse. Three different words in one list
   makes the band look like three different controls, and the label would
   change under the reader's finger the moment a match went live.

   It has been a chip in the meta column and, before that, two stacked lines
   there. Both were the same mistake: the smallest target in the row was the
   one control whose entire job is to be pressed, tucked in the far corner at
   seventy-odd pixels wide. Across the bottom it is roughly seven times the
   area, and it sits under the score the eye has just finished reading.

   NO PILL. A rounded capsule reads as a discrete little button — you aim at
   the capsule. A square-ended band that runs wall to wall reads as a strip,
   and a strip invites a press anywhere along it, which is exactly the point.
   Squared off, edge to edge, with only the row's own rounded bottom corners
   (via .mrow's overflow:hidden) softening it. */
.m-open{display:flex;align-items:center;justify-content:center;gap:6px;
 width:100%;font:inherit;cursor:pointer;
 background:rgba(231,198,107,.08);
 border:0;border-top:1px solid rgba(231,198,107,.22);border-radius:0;
 color:var(--gold);padding:9px 12px;transition:.15s;}
.m-open span{font-size:9.5px;font-weight:900;letter-spacing:.12em;
 text-transform:uppercase;line-height:1;}
.m-open svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2.6;
 stroke-linecap:round;stroke-linejoin:round;flex:none;}
.m-open:hover{background:rgba(231,198,107,.2);color:#fff;}
/* ── Upcoming ─────────────────────────────────────────────────────────────
   A match not played yet. Dashed, because that is already this site's mark
   for provisional — the qualifying group's rule, the panel's Upcoming pill —
   and a shade brighter than the played band, because on a player's route it
   is the row worth looking at: the next one.

   Still unmistakably the same control. Same height, same word order, same
   chevron; only the tense and the texture change. */
.m-open.soon{background:rgba(231,198,107,.14);
 border-top:1px dashed rgba(231,198,107,.55);color:var(--gold);}
.m-open.soon:hover{background:rgba(231,198,107,.26);color:#fff;}
.mrow[data-mid]:hover .m-open.soon{background:rgba(231,198,107,.22);}
/* Inset, because an outline drawn OUTSIDE a full-bleed band is clipped away
   by .mrow's overflow:hidden and the keyboard user gets no ring at all. */
.m-open:focus-visible{outline:2px solid var(--gold);outline-offset:-3px;}
/* The band lights when the row is hovered, so the whole row reads as one
   target even though the band is the part that announces itself. */
.mrow[data-mid]:hover .m-open{background:rgba(231,198,107,.16);}
.m-tag{font-size:8.5px;font-weight:900;letter-spacing:.11em;text-transform:uppercase;
 padding:4px 9px;border-radius:999px;white-space:nowrap;}
.m-tag.final{background:rgba(231,198,107,.16);color:var(--gold);}
.m-tag.live{background:var(--red);color:#fff;}
/* ── The LIVE pill breathes ────────────────────────────────────────────────
   A static red pill saying "Live" is a claim; a pulsing one is evidence. On a
   page that now refreshes itself every 25 seconds without the reader touching
   anything, the movement is the only thing telling them it is still connected
   — a frozen score and a working one otherwise look identical.

   The glow rides on box-shadow rather than opacity so the word stays fully
   legible throughout. A label that fades out is a label you cannot read half
   the time.

   prefers-reduced-motion is honoured. Looping animation triggers migraine and
   motion sickness for some people, and nothing here is load-bearing — the pill
   is still red and still says Live standing perfectly still. */
@keyframes livePill{
 0%  {box-shadow:0 0 0 0 rgba(224,20,43,.9);}
 60% {box-shadow:0 0 0 10px rgba(224,20,43,0);}
 100%{box-shadow:0 0 0 0 rgba(224,20,43,0);}
}
.m-tag.live{animation:livePill 1.5s ease-out infinite;}
@media(prefers-reduced-motion:reduce){
 .m-tag.live{animation:none;}
}

.m-tag.sched{background:transparent;color:var(--soft);border:1.3px solid var(--soft);}

/* ── THE TENSE TAGS ────────────────────────────────────────────────────────
   FINISHED and UPCOMING, under the day and time. They use the same vocabulary
   as the match panel's pills, so the two surfaces agree without anyone having
   to learn a second language:

     LIVE      solid red, pulsing        happening now
     FINISHED  hollow, solid border      it is over
     UPCOMING  hollow, DASHED border     provisional, not happening yet

   Neither is gold. Gold on this site means live-adjacent — the Complete pill
   in the panel, the just-finished card in the rail — and a match that ended on
   Sunday should not wear the same colour as one that ended a minute ago.

   ⚠️ SMALLER THAN THE LIVE PILL ON PURPOSE. The meta column is 84px wide (70
   on a phone) and "FINISHED" is eight characters. At the LIVE pill's 8.5px
   with .11em tracking it measures about 74px including padding and simply does
   not fit — it would wrap mid-word or push the column into the names, which is
   the width the names were given in the first place. 7.5px and tighter
   tracking brings it to ~60px, inside the column with room to spare. */
.m-tag.done,.m-tag.soon{font-size:7.5px;letter-spacing:.05em;padding:3px 7px;
 background:transparent;color:var(--soft);}
.m-tag.done{border:1.2px solid rgba(159,179,212,.45);}
.m-tag.soon{border:1.2px dashed rgba(159,179,212,.5);}
/* The estimate mark. Gold so it reads as a footnote reference rather than
   punctuation, and small enough that it never competes with the time it
   qualifies. aria-hidden on the row copies: a screen reader hitting 127
   asterisks learns nothing, and the note itself is read out at the top. */
/* Regular weight, like the copy it marks. Size stays relative so the asterisk
   tracks whatever it is attached to — the time on a row, the footnote below a
   round rule — instead of needing a value per context. */
.m-est{color:var(--gold);font-size:.7em;font-weight:400;margin-left:1px;}
.m-when{font-size:9.5px;font-weight:800;color:var(--soft);letter-spacing:.04em;text-align:center;}
/* The time is the thing people scan for, so it outranks the date it sits
   under — white against the date's muted blue, and a size larger. */
.m-time{font-size:11.5px;font-weight:900;color:#fff;letter-spacing:0;
 text-align:center;font-variant-numeric:tabular-nums;white-space:nowrap;}
/* Session and court, the line that actually tells you where to be. Quiet
   against the time above it — you look up the time first, then confirm. */
.m-where{font-size:8.5px;font-weight:800;letter-spacing:.05em;color:var(--soft);
 text-align:center;line-height:1.3;}
.m-note{font-size:8.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
 color:#ffb3bd;}

@media(max-width:560px){
 .m-body{padding:9px 10px 9px 6px;}
 /* Short names on a phone, and smaller. The meta column is narrower now that
 only a live match carries a tag, so the extra width goes to the name. */
 .nm-full{display:none;}
 .nm-short{display:inline;}
 .m-name{font-size:12.5px;}
 .m-side{gap:6px;}
 /* +6px: the column gained the tense tag, and "UPCOMING" is the widest thing
    in it. Taken from the row's own padding rather than from the names. */
 .m-meta{width:76px;padding:6px 4px;}
 /* The band is the easiest thing to hit on a phone and should stay that
 way — a shade taller than on desktop, not smaller. */
 .m-open{padding:11px 12px;}
 .m-open span{font-size:9px;letter-spacing:.1em;}
 .m-where{font-size:8px;}
 .m-when{font-size:9px;}
 .m-time{font-size:10.5px;}
 .m-sets i{width:11px;font-size:11.5px;}
 .m-pt{width:27px;font-size:11px;}
 /* Flag stays, letters go. The flag already carries the country, and the
 three letters cost ~22px that the name needs more. */
 .m-ctry{width:16px;}
 .m-ctry .cc{display:none;}
 .m-ctry .flag{margin-right:0;}
}

/* ── The round chip ───────────────────────────────────────────────────────
   Only on surfaces with no round heading — a player's route, where every row
   is a different round. Short form only ("R1", "QF"): the long names are what
   made this column 92px wide on the profile, and the room they cost is the
   room the two names and the scoreline needed.
   First in the meta column, above the Live tag, because on that page the
   round is what you are scanning down. */
.m-rd{font-size:10px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;
 color:var(--gold);}

/* ── A round not reached ──────────────────────────────────────────────────
   Ghosted rather than omitted: five empty rows below "Round 2" say "out in
   round two" far better than a list that simply stops. Nothing to open, so no
   band and no pointer. */
.mrow.ghost{opacity:.42;border-left-color:rgba(255,255,255,.08);cursor:default;}
.mrow.ghost .m-name{font-style:italic;color:var(--soft);font-weight:700;}
.mrow.ghost .m-side{min-height:38px;align-items:center;}
