/*
 * table-predictor.css — /premier-league-table-predictor
 *
 * Loaded on top of rules.css rather than instead of it. The page is built out of the same
 * documentation furniture as /rules/ and /run-a-prediction-league (grey page, white InfoSheet
 * cards, sidebar contents), because everything below the tool is prose and should read like the
 * rest of the site's prose. This file dresses the one part that is not: the draggable table.
 *
 * Two rules the table follows, both of them because of how it is used:
 *
 *   - Rows are a fixed height, and it is the same fixed height at every breakpoint. The drag
 *     works out where a row has been dropped by dividing the pointer's travel by the row height,
 *     so a row that grows because a long club name wrapped would put the club somewhere other
 *     than where the finger let go. Hence `white-space: nowrap` and an ellipsis on the name -
 *     "Nott'm Forest" is the longest and fits at 320px, but a future promoted club might not.
 *   - Colour is never the only channel. The bands are also stated in the position column's
 *     grouping and written out in full in the table under "What the colours mean", so the page
 *     works in greyscale and for anyone who cannot separate the green from the red.
 *
 * The band pair is green600 #698825 and red700 #943838, the same two the bias study uses and the
 * same two that were run through the palette validator there (CVD ΔE 11.6 deutan, 22.8 normal,
 * both over 3:1 on white). Do not substitute one without re-running that check.
 */

/* ---------------------------------------------------------------- the list */

/* Both selectors: `.InfoBody ol` in rules.css indents lists by 20px for the numbering it expects
   to be there, and beats a bare `.tp_list`. On a list whose rows draw their own numbers and their
   own band stripe, that indent is a white column inside the border. */
.tp_list,
.InfoBody ol.tp_list {
    list-style: none;
    margin: 0 0 14px;
    padding: 0;
    border: 1px solid var(--grey200);
    border-radius: 10px;
    overflow: hidden;
    /* The rows are absolutely nothing during a drag if the browser decides the gesture was a
       scroll instead. touch-action is set on the grip rather than here so that the list itself
       still scrolls normally under a finger anywhere else. */
    background: #fff;
}

.tp_row {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 44px;
    box-sizing: border-box;
    padding: 0 10px 0 0;
    border-bottom: 1px solid var(--grey200);
    background: #fff;
    /* Set as a custom property so the JS can read one number rather than measuring, and so the
       height cannot be changed here without the drag maths following it. */
    --tp-row-h: 44px;
}

.tp_row:last-child { border-bottom: 0; }

/* `.InfoBody li + li` in rules.css puts 8px between list items, which is right for the prose
   lists on these pages and wrong for a table. It was also breaking the drag rather than only
   looking wrong: the gesture divides travel by --tp-row-h to find the drop position, so a real
   step of 52px against a declared 44px lost most of a row over a long drag. */
.tp_list .tp_row + .tp_row { margin-top: 0; }

/* Hover, which is a reading aid before it is an affordance. The table gets walked through on
   video and in front of other people, and a pointer resting on a club is how the person talking
   says "this one" - so the whole row lights up rather than just the handle under the cursor.

   Neutral grey on purpose. Every other colour in this table means something (the bands, the kit
   stripes), and a green or red wash under the pointer would read as one of them.

   Nothing moves: no lift, no shift, no border change. The drag already owns movement here, and a
   row that nudges on hover reads as the start of a drag that never happened.

   hover:hover only, or a tap on a phone leaves the row tinted until something else is touched -
   which is exactly the "why is this one selected" confusion the hover is meant to prevent. */
@media (hover: hover) {
    .tp_row:not(.tp_dragging):hover { background: var(--grey200); }

    /* The grip is grey300 so it sits quietly on white, which on a grey200 row leaves it almost
       invisible - and the hovered row is the one whose handle is about to be grabbed. */
    .tp_row:not(.tp_dragging):hover .tp_grip::before {
        background: var(--grey500);
        box-shadow: 0 -6px 0 var(--grey500), 0 6px 0 var(--grey500);
    }

    /* background-color and nothing else. A blanket `all` here would ease the transforms the
       drag puts on these rows, and the drag measures them again immediately. */
    .tp_row { transition: background-color 90ms ease; }
}

.tp_pos {
    flex: 0 0 44px;
    text-align: center;
    font-weight: 700;
    font-size: 15px;
    color: var(--grey700);
    /* The band stripe. Its own element would be a fifth node in every row for no gain. */
    border-left: 6px solid transparent;
    align-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Kit colours, drawn as the shirt's own stripes - Newcastle and Brighton are four, Man Utd three,
   Chelsea one. Decoration, never an encoding: the club's name is right beside it, which is the
   condition docs/supported_team.md §1.2 puts on using colour at all.

   Wide enough that four stripes are still four stripes at 4px each. The inset ring is load
   bearing rather than a nicety: Brighton, Leeds, Spurs and Forest all lead with white and would
   otherwise lose a stripe, or all of them, into the row. */
.tp_kit {
    flex: 0 0 16px;
    height: 20px;
    border-radius: 2px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
    margin-right: -2px;
}

.tp_club {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--grey900);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ------------------------------------------------------------------- bands */

.tp_band_champ .tp_pos { border-left-color: var(--yellow500); background: var(--yellow100); }
.tp_band_ucl   .tp_pos { border-left-color: var(--green600);  background: var(--green100); }
.tp_band_euro  .tp_pos { border-left-color: var(--green300);  background: var(--green100); }
.tp_band_mid   .tp_pos { border-left-color: var(--grey200); }
.tp_band_rel   .tp_pos { border-left-color: var(--red700);    background: var(--red100); }

/* The legend swatches in the "what the colours mean" table reuse the band classes, so a colour
   changed above changes in both places. They are not .tp_pos, hence the separate rule. */
.tp_swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    margin-right: 8px;
    vertical-align: -1px;
    background: var(--grey300);
}
.tp_swatch.tp_band_champ { background: var(--yellow500); }
.tp_swatch.tp_band_ucl   { background: var(--green600); }
.tp_swatch.tp_band_euro  { background: var(--green300); }
.tp_swatch.tp_band_rel   { background: var(--red700); }

.tp_bands_table td:first-child { white-space: nowrap; }

/* ---------------------------------------------------------------- controls */

.tp_controls {
    flex: 0 0 auto;
    display: flex;
    gap: 4px;
}

.tp_move {
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--grey200);
    border-radius: 7px;
    background: var(--grey100);
    color: var(--grey700);
    font-size: 14px;
    cursor: pointer;
    /* A 30px control is under the 44px touch target guidance, which is a real cost here. It buys
       a 44px row, and the row height is what keeps twenty clubs on one phone screen without
       scrolling - which is the whole feel of the thing. The drag handle beside it is full row
       height and is the primary way to move a club; these are the precise fallback. */
    display: flex;
    align-items: center;
    justify-content: center;
}

.tp_move:hover { background: var(--green100); border-color: var(--green300); color: var(--green800); }
.tp_move:disabled { opacity: 0.3; cursor: default; }
.tp_move:disabled:hover { background: var(--grey100); border-color: var(--grey200); color: var(--grey700); }

/* Three bars, drawn rather than iconised: the FontAwesome subset has no grip glyph, and adding
   one means regenerating the font (docs/fontawesome-subset.md) to draw six pixels of lines. */
.tp_grip {
    flex: 0 0 34px;
    align-self: stretch;
    cursor: grab;
    /* Load-bearing. Without it the browser claims a vertical drag as a scroll and the pointer
       events stop arriving mid-gesture, so a row follows the finger and then abandons it. */
    touch-action: none;
    position: relative;
}

/* One element, three bars: the middle one is the box, the other two are its shadows. */
.tp_grip::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 18px;
    height: 2px;
    margin: -1px 0 0 -9px;
    border-radius: 1px;
    background: var(--grey300);
    box-shadow: 0 -6px 0 var(--grey300), 0 6px 0 var(--grey300);
}

.tp_help {
    font-size: 13px;
    color: var(--grey600);
    margin: 0 0 18px;
}

/* ------------------------------------------------------------- drag states */

/* The row under the finger. Lifted off the list and moved with a transform, so it never changes
   the layout of the rows it is passing over - those are shifted by a transform of their own. */
.tp_row.tp_dragging {
    position: relative;
    z-index: 3;
    background: #fff;
    box-shadow: 0 6px 18px var(--shadow);
    border-radius: 8px;
    border-bottom-color: transparent;
}

.tp_row.tp_dragging .tp_grip { cursor: grabbing; }

/* Every other row while a drag is running. The transition is on this class rather than on
   .tp_row so the dragged row itself tracks the finger with no easing behind it. */
.tp_row.tp_shifting {
    transition: transform 120ms ease;
}

/* ---------------------------------------------------------------- actions */

.tp_actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
}

.tp_btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 11px 18px;
    border: 1px solid var(--grey300);
    border-radius: 8px;
    background: #fff;
    color: var(--grey800);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
}

.tp_btn:hover { background: var(--grey100); }

.tp_btn_primary {
    background: var(--green700);
    border-color: var(--green700);
    color: #fff;
}
.tp_btn_primary:hover { background: var(--green800); border-color: var(--green800); }

.tp_btn_quiet {
    background: transparent;
    border-color: transparent;
    color: var(--grey600);
    padding-left: 8px;
    padding-right: 8px;
}
.tp_btn_quiet:hover { background: var(--grey100); color: var(--grey800); }

.tp_status {
    flex-basis: 100%;
    margin: 0;
    min-height: 20px;
    font-size: 14px;
    color: var(--green800);
}

/* The status line is empty until somebody shares or copies, and for the whole of that time its
   reserved 20px plus the flex gap plus its line box sat between the Reset button and the bottom
   of the sheet as dead white. The league card is the next thing down the page, so every pixel
   here is a pixel later that the ask starts to appear.

   Collapsed rather than display:none deliberately. This carries role="status" aria-live="polite",
   and a live region that is display:none is out of the accessibility tree - screen readers are
   unreliable about announcing text that arrives in the same frame the element becomes visible.
   Zero height keeps it rendered and announceable while taking no room.

   Scoped under .InfoBody to win a specificity fight rather than to say where it lives. This is a
   <p>, and `.InfoBody p { margin-bottom: 16px }` in rules.css is (0,2,0) where the `.tp_status`
   rule above is (0,1,0) - so that margin has been outranking `margin: 0` all along and was 16 of
   the pixels being removed here. `.InfoBody .tp_status:empty` is (0,3,0) and settles it. Second
   time this page has been caught by an .InfoBody descendant rule; the first was the link colour
   on a button. Anything single-class inside that column is worth checking against it. */
.InfoBody .tp_status:empty {
    min-height: 0;
    height: 0;
    margin-bottom: 0;
    overflow: hidden;
}

/* The tool's own sheet only. The four pages that share .InfoSheet - /rules/,
   /run-a-prediction-league, /bbc-predictor-alternative and the sections further down this page -
   are prose, where the trailing padding is the reading margin and should stay. This one ends in a
   row of buttons, and what follows it is the one ask on the page. */
.InfoSheet.tp_sheet { padding-bottom: 0; margin-bottom: 8px; }
.InfoSheet.tp_sheet .InfoBody { padding-bottom: 0; }

/* ---------------------------------------------------------------- preview */

.tp_preview {
    position: fixed;
    inset: 0;
    z-index: 50;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    overflow: auto;
}

.tp_preview[hidden] { display: none; }

.tp_preview_inner {
    background: #fff;
    border-radius: 12px;
    padding: 20px;
    max-width: 420px;
    width: 100%;
    text-align: center;
}

.tp_preview_inner h2 {
    font-size: 19px;
    margin: 0 0 14px;
    color: var(--grey900);
}

.tp_preview_inner img {
    width: 100%;
    height: auto;
    border: 1px solid var(--grey200);
    border-radius: 8px;
    display: block;
    margin-bottom: 16px;
}

.tp_preview_actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

/* ------------------------------------------------------------ league card */

/* Sits in the column of InfoSheets but is not one: green rather than white, so the one ask on a
   page of documentation does not read as another paragraph of it. Same green100/green300 pair the
   band legend uses, so no new colour enters the page. */
.tp_league {
    background: var(--green100);
    border: 1px solid var(--green300);
    border-radius: 12px;
    padding: 24px;
    margin-bottom: 20px;
}

.tp_league h2 {
    font-size: 21px;
    margin: 0 0 10px;
    color: var(--green900);
}

.tp_league p {
    margin: 0 0 18px;
    max-width: 52ch;
}

/* Full width of the card, directly under the heading.

   This was a 780x1380 phone screenshot capped at 190px and floated beside the copy from 700px up.
   Both of those are gone with the image they were built for: at 190px wide the ten names in the
   shot rendered about four pixels tall, which is a picture of the thing rather than a look at it.
   The replacement is a 780x285 crop of a single live match row, so it wants the width rather than
   a column beside the text, and the card is one stack at every size again.

   Capped at its own intrinsic width so a wide screen never upscales it into softness. */
.tp_league_shot {
    margin: 16px 0 18px;
    max-width: 780px;
}

.tp_league_shot img {
    width: 100%;
    height: auto;
    display: block;
    border: 1px solid var(--grey200);
    border-radius: 10px;
}

/* ------------------------------------------------------------------- toc */

/* No "On this page" on a phone, and only on this page.

   rules.css turns the sidebar into a row of pills below 900px, which works where the sheets are
   prose and the pills are how you skip to the section you want. Here the thing everybody came for
   is the tool, the tool is the first sheet, and the pills push it down the screen to be scrolled
   past by people who are not going to read the FAQ.

   Scoped on body.tp_page so /rules/, /run-a-prediction-league and /bbc-predictor-alternative keep
   theirs. They are documentation, where a contents list is the point; this is a tool with
   documentation under it. 900px is rules.css's own breakpoint, matched rather than picked, so the
   sidebar is either a sidebar or gone and never a row of pills. */
@media (max-width: 900px) {
    .tp_page .rules_toc { display: none; }
}

/* ------------------------------------------------------------------ small */

@media (max-width: 420px) {
    .tp_pos  { flex-basis: 36px; font-size: 14px; }
    .tp_kit  { flex-basis: 14px; height: 18px; }
    .tp_club { font-size: 15px; }
    .tp_move { width: 28px; height: 28px; }
    .tp_grip { flex-basis: 28px; }

    .tp_league { padding: 18px; }
    .tp_league h2 { font-size: 19px; }
}

/* -------------------------------------------------------------- 320px wide */

/* At 320 the row ran out of room and the club name was the part that gave way: seven of the
   twenty ellipsised, "Crystal Palace" and "Nott'm Forest" among them, which is the whole content
   of the page. Everything else in the row gives back a few pixels, and the sheet's own padding
   halves - this is the one sheet on the page whose content is a table rather than prose, so the
   reading margin it is there to provide is not doing anything. */
@media (max-width: 360px) {
    .InfoSheet.tp_sheet { padding-left: 4px; padding-right: 4px; }

    .tp_row  { gap: 6px; padding-right: 6px; }
    .tp_pos  { flex-basis: 30px; }
    .tp_kit  { flex-basis: 12px; }
    .tp_club { font-size: 14px; }
    .tp_move { width: 26px; height: 26px; }
    .tp_grip { flex-basis: 24px; }
}
