/* ==========================================================================
   Bracketworks: the app's own stylesheet.

   Bracketworks is a working tool, not a page about a tool, so this file is a small
   product design system rather than a page layout: chrome, controls, panels,
   tables and states. It consumes /tokens.css and adds nothing to it.

   THE GROUND SHIFTS, THE SEMANTICS DO NOT
   ---------------------------------------
   Exactly the pattern /woodworking-designs already uses. The studio's semantic
   tokens are aliased ONCE onto the --bracket-* ramp, and every rule below, plus
   the header lifted in style from index.html, resolves to pool blue without
   being rewritten. Dark mode comes free: tokens.css swaps --bracket-* under
   [data-theme="dark"] and an alias follows whatever it points at.

   Audited before it landed: worst pair is 4.60:1 (accent on sunken, light) and
   7.22:1 (accent on surface, dark). AA throughout, AAA for body text.

   SHAPE
   -----
   The studio's rule, tightened for a dense tool: buttons are pill, panels are
   md, small chrome is sm. Control height is 34px, not the 48px of a landing
   page CTA, because a match-day desk fits more on the screen.

   COLOUR IS NEVER THE ONLY SIGNAL
   -------------------------------
   Team colours come from a small categorical set, and every coloured chip also
   carries the team's short code. Status uses no new hues: confirmed is the
   accent, pending is the studio's marigold, conflict is its cherry.

   HOUSE STYLE
   -----------
   No em-dashes anywhere in the visible copy.
   ========================================================================== */

/* ---- the one aliasing block --------------------------------------------- */
:root{
  --color-bg:             var(--bracket-bg);
  --color-surface:        var(--bracket-surface);
  --color-surface-sunken: var(--bracket-sunken);
  --color-text:           var(--bracket-ink);
  --color-text-muted:     var(--bracket-muted);
  --color-text-faint:     color-mix(in oklab, var(--bracket-muted) 72%, var(--bracket-bg));
  --color-border:         var(--bracket-line);
  --color-border-strong:  color-mix(in oklab, var(--bracket-line) 70%, var(--bracket-ink));
  --color-accent:         var(--bracket-primary);
  --color-accent-strong:  var(--bracket-primary);
  --color-accent-ink:     var(--bracket-deep);
  --color-accent-hover:   var(--bracket-deep);
  --color-accent-quiet:   var(--bracket-sunken);
  --color-on-accent:      #FFFFFF;

  /* Control metrics. One scale, used by every button, input and select. */
  --ctl-h:    34px;
  --ctl-h-sm: 28px;
  --ctl-h-lg: 44px;

  /* Status. No new hues: the accent, the studio's marigold, the studio's
     cherry. Each is paired with a quiet ground for its own chip. */
  --state-ok:        var(--bracket-primary);
  --state-ok-quiet:  var(--bracket-sunken);
  --state-wait:      var(--marigold-700);
  --state-wait-quiet:var(--marigold-100);
  --state-bad:       var(--cherry-700);
  --state-bad-quiet: #F7E3E3;
}
:root[data-theme="dark"]{
  --color-on-accent:      #04141C;
  --state-wait:           var(--marigold-300);
  --state-wait-quiet:     #3A2E05;
  --state-bad:            var(--cherry-300);
  --state-bad-quiet:      #3B1417;
}

/* ---- reset and page ----------------------------------------------------- */
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  min-height:100dvh;
  background:var(--color-bg);color:var(--color-text);
  font-family:var(--font-text);font-size:var(--text-body);line-height:var(--leading-body);
  -webkit-font-smoothing:antialiased;
}
:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px;border-radius:4px}
.wrap{max-width:var(--page);margin:0 auto;padding:0 var(--space-6)}
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}
[hidden]{display:none !important}

/* ==========================================================================
   Header. One line, capped at the studio's 68px, same chrome vocabulary as
   index.html so walking in from the studio does not feel like a new site.
   The brand reads as a path: the studio, then this app.
   ========================================================================== */
.appbar{
  height:var(--header-h);display:flex;align-items:center;
  border-bottom:var(--border-width) solid var(--color-border);
  background:var(--color-surface);
  position:sticky;top:0;z-index:20;
}
.appbar .wrap{display:flex;align-items:center;gap:var(--space-4);width:100%}
.brand{display:flex;align-items:center;gap:var(--space-3);flex-shrink:0}
/* The studio and the app are two destinations, so they are two links. */
.brand a{display:flex;align-items:center;gap:var(--space-3);text-decoration:none;border:0}
.brand img{display:block;width:30px;height:30px;flex-shrink:0}
.brand .jc-mark{width:30px;height:30px}
.brand b{
  font-family:var(--font-display);font-size:1.0625rem;font-weight:var(--weight-display);
  letter-spacing:-.02em;color:var(--color-text);white-space:nowrap;
}
.brand .studio{
  color:var(--color-text-faint);font-size:var(--text-sm);font-weight:var(--weight-medium);
  white-space:nowrap;
}
.brand .studio::after{content:"/";margin-left:var(--space-2);color:var(--color-border-strong)}
.brand-studio:hover .studio{color:var(--color-text-muted)}
.brand-app:hover b{color:var(--color-accent-strong)}

.appnav{display:flex;align-items:center;gap:var(--space-1);margin-left:var(--space-6);min-width:0;overflow-x:auto}
.appnav a{
  display:inline-flex;align-items:center;height:var(--ctl-h);padding:0 var(--space-4);
  border-radius:var(--radius-pill);text-decoration:none;white-space:nowrap;
  color:var(--color-text-muted);font-size:var(--text-body);font-weight:var(--weight-medium);
  transition:color var(--duration) var(--ease),background var(--duration) var(--ease);
}
.appnav a:hover{color:var(--color-text);background:var(--color-surface-sunken)}
.appnav a[aria-current="page"]{color:var(--color-on-accent);background:var(--color-accent-strong)}
/* A tab carries its own state, which is how the app says what is next without
   a tour or a tooltip: Teams 6, Draw to do, Schedule to do. */
.appnav a{gap:var(--space-2)}
.tabstate{
  font-family:var(--font-mono);font-size:var(--text-label);
  font-variant-numeric:tabular-nums;
  padding:1px var(--space-2);border-radius:var(--radius-pill);
  background:var(--color-surface-sunken);color:var(--color-text-faint);
}
.appnav a[aria-current="page"] .tabstate{
  background:color-mix(in oklab,var(--color-on-accent) 22%,transparent);
  color:var(--color-on-accent);
}
.appnav a.notyet{opacity:.5}

/* ---- the ? hint ---------------------------------------------------------
   Native popover: the top layer, Escape and click-outside come from the
   browser, so there is no state to keep and nothing to tear down. */
.hint-wrap{display:inline-flex;vertical-align:middle;margin-left:var(--space-2)}
.hint{
  width:18px;height:18px;padding:0;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  border:var(--border-width) solid var(--color-border-strong);border-radius:var(--radius-pill);
  background:var(--color-surface);color:var(--color-text-muted);
  font-family:var(--font-text);font-size:11px;font-weight:var(--weight-semi);line-height:1;
  cursor:pointer;
  transition:color var(--duration) var(--ease),border-color var(--duration) var(--ease);
}
.hint:hover{color:var(--color-on-accent);background:var(--color-accent-strong);border-color:var(--color-accent-strong)}
.hint-bubble{
  max-width:min(30rem,calc(100vw - var(--space-8)));
  padding:var(--space-4) var(--space-5);
  border:var(--border-width) solid var(--color-border-strong);border-radius:var(--radius-md);
  background:var(--color-surface);color:var(--color-text);
  font-size:var(--text-sm);line-height:var(--leading-sm);
  box-shadow:var(--shadow-md);
}
.hint-bubble::backdrop{background:color-mix(in oklab,var(--bracket-ink) 28%,transparent)}
.hint-bubble b{
  display:block;font-family:var(--font-display);font-size:var(--text-body);
  margin-bottom:var(--space-2);
}

.appbar .spacer{margin-left:auto}
.appbar .tools{display:flex;align-items:center;gap:var(--space-2);flex-shrink:0}

/* ==========================================================================
   Controls
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);
  height:var(--ctl-h);padding:0 var(--space-5);
  border-radius:var(--radius-pill);border:var(--border-width) solid var(--color-border);
  background:var(--color-surface);color:var(--color-text);
  font-family:var(--font-text);font-size:var(--text-body);font-weight:var(--weight-semi);
  line-height:1;white-space:nowrap;text-decoration:none;cursor:pointer;
  transition:background var(--duration) var(--ease),border-color var(--duration) var(--ease),
             color var(--duration) var(--ease);
}
.btn:hover{border-color:var(--color-accent);color:var(--color-accent-ink)}
.btn:active{transform:translateY(1px)}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed;transform:none}
.btn[disabled]:hover,.btn[aria-disabled="true"]:hover{border-color:var(--color-border);color:var(--color-text)}
.btn.primary{
  background:var(--color-accent-strong);border-color:var(--color-accent-strong);
  color:var(--color-on-accent);
}
.btn.primary:hover{background:var(--color-accent-hover);border-color:var(--color-accent-hover);color:var(--color-on-accent)}
.btn.ghost{background:transparent;border-color:transparent;color:var(--color-text-muted);font-weight:var(--weight-medium)}
.btn.ghost:hover{background:var(--color-surface-sunken);color:var(--color-text)}
.btn.danger:hover{border-color:var(--state-bad);color:var(--state-bad)}
.btn.lg{height:var(--ctl-h-lg);padding:0 var(--space-6);font-size:1rem}
.btn.sm{height:var(--ctl-h-sm);padding:0 var(--space-3);font-size:var(--text-sm)}
.btn svg{display:block;flex-shrink:0}

.icon-btn{
  width:var(--ctl-h);height:var(--ctl-h);flex-shrink:0;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--color-surface);border:var(--border-width) solid var(--color-border);
  border-radius:var(--radius-pill);color:var(--color-text-muted);cursor:pointer;
  transition:color var(--duration) var(--ease),border-color var(--duration) var(--ease);
}
.icon-btn:hover{color:var(--color-accent);border-color:var(--color-accent)}
.icon-btn svg{display:block}
.icon-btn.bare{border-color:transparent;background:transparent}
.icon-btn.bare:hover{background:var(--color-surface-sunken);border-color:transparent}
/* Both glyphs live in the button and one is hidden. These selectors carry the
   .icon-btn prefix on purpose: `.icon-btn svg{display:block}` above outweighs a
   bare `.to-light{display:none}`, which is how you end up with a sun printed on
   top of a moon. */
.icon-btn svg.to-dark{display:block}
.icon-btn svg.to-light{display:none}
:root[data-theme="dark"] .icon-btn svg.to-dark{display:none}
:root[data-theme="dark"] .icon-btn svg.to-light{display:block}

/* ---- fields. Label above, helper optional, error below. Never a placeholder
        standing in for a label. ---------------------------------------------- */
.field{display:flex;flex-direction:column;gap:var(--space-2);min-width:0}
.field > label{
  font-size:var(--text-sm);font-weight:var(--weight-semi);color:var(--color-text);
}
/* Helper text. One sentence explaining the control, the panel or the table it
   sits under. This used to be `.field .help` and nothing else, while `.help`
   itself was the name of the written walkthrough's wrapper: two things under
   one word. Every `<p class="help">` outside a field, which is most of them,
   therefore came out as full strength body copy at the walkthrough's 46rem
   measure. Under a table of fifteen fixtures that reads as another row of the
   table rather than as a note about it. The walkthrough is .helpdoc now, and
   this is helper text everywhere. */
.help{
  font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--color-text-muted);
  max-width:var(--measure);margin:0 0 var(--space-3);
}
.field .help{margin:0}
.field .err{font-size:var(--text-sm);color:var(--state-bad);margin:0;font-weight:var(--weight-medium)}
input[type=text],input[type=number],input[type=date],input[type=time],input[type=search],select,textarea{
  height:var(--ctl-h);width:100%;min-width:0;padding:0 var(--space-3);
  background:var(--color-surface);color:var(--color-text);
  border:var(--border-width) solid var(--color-border-strong);border-radius:var(--radius-sm);
  font-family:var(--font-text);font-size:var(--text-body);
  transition:border-color var(--duration) var(--ease);
}
textarea{height:auto;min-height:76px;padding:var(--space-2) var(--space-3);line-height:var(--leading-body);resize:vertical}
input:hover,select:hover,textarea:hover{border-color:var(--color-accent)}
input::placeholder,textarea::placeholder{color:var(--color-text-faint)}
input[aria-invalid="true"],select[aria-invalid="true"]{border-color:var(--state-bad)}
select{appearance:none;padding-right:var(--space-8);
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 16px) 14px,calc(100% - 11px) 14px;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
input[type=number]{font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.field.inline{flex-direction:row;align-items:center;gap:var(--space-3)}
.field.inline > label{flex:0 0 auto}

/* ==========================================================================
   Surfaces
   ========================================================================== */
.panel{
  background:var(--color-surface);
  border:var(--border-width) solid var(--color-border);
  border-radius:var(--radius-md);
}
.panel > header{
  display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;
  padding:var(--space-4) var(--space-5);
  border-bottom:var(--border-width) solid var(--color-border);
}
.panel > header h2{
  font-family:var(--font-display);font-size:var(--text-h3);line-height:var(--leading-h3);
  font-weight:var(--weight-display);margin:0;letter-spacing:var(--tracking-h3);
}
.panel > header .spacer{margin-left:auto}
.panel > .body{padding:var(--space-5)}
.panel > .body.flush{padding:0}

main{padding:var(--space-8) 0 var(--space-16)}
.viewhead{
  display:flex;align-items:flex-end;gap:var(--space-4);flex-wrap:wrap;
  margin:0 0 var(--space-6);
}
.viewhead h1{
  font-family:var(--font-display);
  font-size:clamp(1.5rem,3vw,2rem);line-height:1.15;letter-spacing:-.015em;
  font-weight:var(--weight-display);margin:0;
}
.viewhead p{margin:var(--space-1) 0 0;color:var(--color-text-muted)}
.viewhead .spacer{margin-left:auto}
.toolbar{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}

/* ==========================================================================
   Data table. Density 7: rows are tight, numbers are mono and tabular, and one
   hairline separates rows. No border on every side of every cell.
   ========================================================================== */
.table{width:100%;border-collapse:collapse;font-size:var(--text-sm)}
.table th,.table td{padding:var(--space-2) var(--space-4);text-align:left;vertical-align:middle}
.table thead th{
  font-size:var(--text-label);letter-spacing:.06em;text-transform:uppercase;
  font-weight:var(--weight-semi);color:var(--color-text-muted);
  border-bottom:var(--border-width) solid var(--color-border-strong);
  white-space:nowrap;background:var(--color-surface);
}
.table tbody tr + tr td{border-top:var(--border-width) solid var(--color-border)}
.table tbody tr:hover td{background:var(--color-surface-sunken)}

/* A whole row that opens something. The link inside it stays the real control,
   so the keyboard and a screen reader still have something to land on; this is
   only the mouse target being the size it looks. */
.table tbody tr.rowlink{cursor:pointer}
.table tbody tr.rowlink a{
  color:var(--color-accent-ink);font-weight:var(--weight-semi);text-decoration:none;
}
.table tbody tr.rowlink:hover a{text-decoration:underline}
.table tbody tr.rowlink:focus-within td{background:var(--color-accent-quiet)}
.table .num{
  font-family:var(--font-mono);font-variant-numeric:tabular-nums;text-align:right;
  white-space:nowrap;
}
.table .shrink{width:1%;white-space:nowrap}
/* The days table has one wide column and three narrow ones, so the date field
   absorbed the whole panel: a 670px box for eight characters. A date is a date
   wherever it is typed. */
.table.days td input[type=date]{max-width:11rem}
.table td .btn.sm{vertical-align:middle}
.scroll-x{overflow-x:auto;-webkit-overflow-scrolling:touch}
/* A fixture table and a timetable are laid out at a fixed 46rem, so below that
   they always overflow their panel and above it they never do. The tab strip
   got a fade at its right edge to say the row keeps going; these did not, and
   on a phone that is 736px of match inside a 358px panel with nothing to
   suggest the rest is reachable. Same fade, same reason, and it is inside one
   media query rather than guessed at, because at this width the overflow is a
   certainty rather than a possibility. */
@media (max-width:860px){
  .scroll-x:has(> .table.fixtures),
  .scroll-x:has(> .table.timetable){
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
            mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
  }
}
/* Paper does not scroll, so the fade would only shave the last column off the
   right hand side of a printed sheet. */
@media print{.scroll-x{-webkit-mask-image:none!important;mask-image:none!important}}

/* ---- chips and pills ---------------------------------------------------- */
.chip{
  display:inline-flex;align-items:center;gap:var(--space-2);
  height:var(--ctl-h-sm);padding:0 var(--space-3);
  border-radius:var(--radius-pill);background:var(--color-surface-sunken);
  color:var(--color-text);font-size:var(--text-sm);font-weight:var(--weight-medium);
  white-space:nowrap;
}
.chip .swatch{
  width:10px;height:10px;border-radius:3px;flex-shrink:0;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.18);
}
.pill{
  display:inline-flex;align-items:center;height:22px;padding:0 var(--space-3);
  border-radius:var(--radius-pill);
  font-size:var(--text-label);font-weight:var(--weight-semi);
  letter-spacing:.04em;text-transform:uppercase;white-space:nowrap;
}
.pill.mute{color:var(--color-text-muted);background:var(--color-surface-sunken)}
.pill.ok  {color:var(--state-ok);  background:var(--state-ok-quiet)}
.pill.wait{color:var(--state-wait);background:var(--state-wait-quiet)}
.pill.bad {color:var(--state-bad); background:var(--state-bad-quiet)}

/* ==========================================================================
   States. Written here, not retrofitted: a tool that only draws its happy path
   is a demo.
   ========================================================================== */
/* An empty state is a panel with nothing in it yet, so it is drawn as one.
   Standing on the page ground with no edge, it read as a paragraph that had
   come loose: on the tournaments page it sat under a heading, centred, with a
   button under it and nothing saying where the section began or ended. Inside a
   panel it takes the panel's own ground instead, because two borders around one
   thing is worse than none. */
.empty{
  display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:var(--space-4);padding:var(--space-12) var(--space-6);
  color:var(--color-text-muted);
  background:var(--color-surface);
  border:var(--border-width) solid var(--color-border);
  border-radius:var(--radius-md);
}
.panel .empty{background:none;border:0;border-radius:0}
.empty h3{
  font-family:var(--font-display);font-size:var(--text-h3);font-weight:var(--weight-display);
  color:var(--color-text);margin:0;
}
.empty p{margin:0;max-width:34rem;text-wrap:pretty}
.empty .toolbar{justify-content:center}

.notice{
  display:flex;align-items:flex-start;gap:var(--space-3);
  padding:var(--space-3) var(--space-4);border-radius:var(--radius-sm);
  font-size:var(--text-sm);
}
.notice svg{flex-shrink:0;margin-top:2px}
.notice.bad {color:var(--state-bad); background:var(--state-bad-quiet)}
.notice.wait{color:var(--state-wait);background:var(--state-wait-quiet)}
.notice.ok  {color:var(--state-ok);  background:var(--state-ok-quiet)}
.notice p{margin:0}
.notice ul{margin:var(--space-2) 0 0;padding-left:var(--space-5)}

/* Toast: one at a time, bottom centre, announced politely. It reports what
   happened (saved, exported, imported), never decoration. */
#toast{
  position:fixed;left:50%;bottom:var(--space-6);transform:translateX(-50%);
  z-index:60;pointer-events:none;
  display:flex;align-items:center;gap:var(--space-3);
  padding:var(--space-3) var(--space-5);border-radius:var(--radius-pill);
  background:var(--color-text);color:var(--color-bg);
  font-size:var(--text-sm);font-weight:var(--weight-medium);
  box-shadow:var(--shadow-md);
  opacity:0;visibility:hidden;
  transition:opacity var(--duration) var(--ease),visibility var(--duration) var(--ease);
}
#toast[data-show]{opacity:1;visibility:visible}

/* ---- dialogs. Native <dialog>, so Escape and the top layer are free. ----- */
dialog{
  border:var(--border-width) solid var(--color-border);border-radius:var(--radius-md);
  background:var(--color-surface);color:var(--color-text);
  padding:0;width:min(30rem,calc(100vw - var(--space-8)));
  box-shadow:var(--shadow-md);
}
dialog::backdrop{background:color-mix(in oklab,var(--bracket-ink) 45%,transparent)}
dialog > form{display:flex;flex-direction:column}
dialog h2{
  font-family:var(--font-display);font-size:var(--text-h3);font-weight:var(--weight-display);
  margin:0;padding:var(--space-5) var(--space-5) 0;
}
dialog .body{padding:var(--space-5);display:flex;flex-direction:column;gap:var(--space-4)}
dialog .actions{
  display:flex;justify-content:flex-end;gap:var(--space-2);
  padding:var(--space-4) var(--space-5);
  border-top:var(--border-width) solid var(--color-border);
  background:var(--color-surface-sunken);
}

/* ==========================================================================
   The front door. This is what you see with nothing saved, so it is the page
   that has to explain the tool. Left aligned beside the mark, not a centred
   marketing hero: you are already inside the app.
   ========================================================================== */
/* The mark sits above the heading, not beside it.
   Beside it, in a two column grid, the mark was centred against a column three
   times its height, so it floated opposite the gap between the headline and the
   line under it, level with nothing. Worse, it pushed the headline, the lede
   and the buttons 164px in from the gutter while the four steps and the six
   facts below them started at the gutter, so the front door had two left edges.
   Stacked, it has one, and it is the same masthead the studio's document pages
   already use: mark, then the name of the thing, then the thing. */
.door{padding:var(--space-12) 0 var(--space-8)}
.door .wrap{display:block}
.door img,.door .jc-mark{
  display:block;width:104px;height:104px;margin:0 0 var(--space-5);
}
.door h1{
  font-family:var(--font-display);
  font-size:clamp(1.875rem,4.4vw,2.75rem);line-height:1.08;letter-spacing:-.02em;
  font-weight:var(--weight-display);margin:0 0 var(--space-4);text-wrap:balance;
  max-width:20ch;
}
.door p{
  font-size:var(--text-lg);line-height:var(--leading-lg);color:var(--color-text-muted);
  margin:0 0 var(--space-6);max-width:46ch;text-wrap:pretty;
}
.door .toolbar{gap:var(--space-3)}

/* What it does. A two-column definition grid, the same shape index.html uses
   for its facts list, so the family is visible without a new pattern. */
.does{margin:0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:var(--space-6) var(--space-10)}
.does div{margin:0}
.does dt{
  font-family:var(--font-display);font-weight:var(--weight-display);
  font-size:var(--text-body);color:var(--color-text);margin:0 0 2px;
}
.does dd{margin:0;color:var(--color-text-muted);font-size:var(--text-sm);line-height:var(--leading-sm)}

.rule{border:0;border-top:var(--border-width) solid var(--color-border);margin:var(--space-10) 0}

/* The ways out of a tournament. One cell each, holding the button and the
   sentence about that button, so the two cannot come apart the way a row of
   buttons over a row of descriptions always eventually does. auto-fit, so a
   narrow window wraps them rather than squeezing three into the width of one. */
.ways{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:var(--space-6)}
.ways > div{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-3)}
.ways .help{margin:0}

/* A setup form. The fields answer in order and the helper text sits under the
   field it explains, so a field with a long explanation is allowed to be taller
   than its neighbours; what it is not allowed to do is push one of them onto a
   row of its own. `.full` is for the field that is a sentence rather than a
   setting, capped at a measure so a name is not typed across a metre of page. */
.setup{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));
  gap:var(--space-5);align-items:start;
}
.setup .full{grid-column:1 / -1;max-width:26rem}
/* A count of pools is one or two digits and does not need the width of a club
   name to hold them. */
.setup input[type=number]{max-width:7rem}
/* The rule runs the width of the panel, because a rule that stops halfway
   across reads as a mistake; the sentence under it keeps a measure. */
.setup-sum{
  margin:var(--space-5) 0 0;padding-top:var(--space-4);
  border-top:var(--border-width) solid var(--color-border);
  font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--color-text-muted);
}
.setup-sum > span{display:block;max-width:var(--measure)}

/* Four steps in order. Numbered by the list itself rather than by a label typed
   into each one, so they cannot get out of step with each other. */
.steps{
  list-style:none;counter-reset:step;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-6);
}
.steps li{counter-increment:step;display:flex;flex-direction:column;gap:var(--space-1);position:relative;padding-top:var(--space-8)}
.steps li::before{
  content:counter(step);position:absolute;top:0;left:0;
  width:28px;height:28px;display:flex;align-items:center;justify-content:center;
  border-radius:var(--radius-pill);
  background:var(--color-accent-strong);color:var(--color-on-accent);
  font-family:var(--font-display);font-size:var(--text-sm);font-weight:var(--weight-display);
}
/* The line between one step and the next, stopping short of the last. */
.steps li:not(:last-child)::after{
  content:"";position:absolute;top:13px;left:34px;right:calc(-1 * var(--space-6));
  border-top:var(--border-width) solid var(--color-border-strong);
}
.steps b{font-family:var(--font-display);font-size:var(--text-body);font-weight:var(--weight-display)}
.steps span{color:var(--color-text-muted);font-size:var(--text-sm);line-height:var(--leading-sm)}
@media (max-width:860px){
  .steps{grid-template-columns:1fr;gap:var(--space-5)}
  .steps li{padding-top:0;padding-left:var(--space-10)}
  .steps li::before{top:0}
  .steps li:not(:last-child)::after{display:none}
}

/* ==========================================================================
   Footer
   ========================================================================== */
.appfoot{
  border-top:var(--border-width) solid var(--color-border);
  padding:var(--space-8) 0 var(--space-10);margin-top:var(--space-16);
  color:var(--color-text-muted);font-size:var(--text-sm);
}
.appfoot .wrap{display:flex;flex-wrap:wrap;gap:var(--space-4) var(--space-8);align-items:baseline;justify-content:space-between}
.appfoot a{color:var(--color-text-muted);text-decoration:none}
.appfoot a:hover{color:var(--color-accent)}

/* ==========================================================================
   The knockout wall chart.

   One grid column per round, each round's boxes spread evenly down its column
   with space-around. That alone lines a round's boxes up between the two boxes
   that feed them, without any measuring: it is the same halving the bracket
   itself does. The connectors are borders on a pseudo element, so they print,
   they follow the type when it reflows, and there is no SVG to keep in step.
   ========================================================================== */

.bracket{display:flex;gap:var(--space-8);align-items:stretch;min-width:min-content;padding:var(--space-2) 0}
.bcol{display:flex;flex-direction:column;min-width:15rem;flex:1}
/* Equal rows, not space-around. A row is the unit the connectors are measured
   in: half a row is exactly the distance from a box's centre to the centre of
   the box it feeds, whatever the round holds. The rows carry no gap, because a
   gap is subtracted from the row height and a round of four then no longer
   lines up with the round of two beside it. The air between boxes comes from
   the slot's own padding, which is inside the row and so is the same in every
   one of them. */
.bslot{position:relative;display:flex;align-items:center;padding:var(--space-1) 0}
.bslot > .bx{flex:1;min-width:0}
.bcol > h3{
  font-family:var(--font-display);font-size:var(--text-label);
  letter-spacing:.1em;text-transform:uppercase;font-weight:var(--weight-semi);
  color:var(--color-text-muted);margin:0 0 var(--space-3);
}
.bcol-body{flex:1;display:grid;grid-auto-rows:1fr;gap:0}

.bx{
  position:relative;
  background:var(--color-surface);
  border:var(--border-width) solid var(--color-border);
  border-radius:var(--radius-sm);
  padding:var(--space-2) var(--space-3);
}
.bx.done{border-color:var(--color-border-strong)}
.bx.dead{opacity:.55;border-style:dashed}
.bx-slot{
  font-size:var(--text-label);letter-spacing:.06em;text-transform:uppercase;
  color:var(--color-text-faint);margin-bottom:var(--space-1);
}
.bx .side{
  display:flex;align-items:center;gap:var(--space-2);
  padding:2px 0;min-height:26px;
}
.bx .side + .side{border-top:var(--border-width) solid var(--color-border)}
.bx .side .who{flex:1;min-width:0}

/* The elbow into the next round.
   This used to be one stub off each box's right edge, half the column gap wide,
   on the theory that it met its neighbour's. It met nothing: the round it feeds
   draws no stub of its own, and its box sits between the two that feed it, not
   level with either, so the line stopped in mid air a round short of the match
   it was pointing at.
   A bracket connector is three segments, and all three are here. Out of each
   box to the middle of the gap; down or up the middle of the gap to the height
   of the match being fed; then across into it. The middle run is half a row,
   which is exactly the distance worked out in .bslot above, so nothing is
   measured at runtime and it survives being printed.
   The top box of each pair carries the run across, as the bottom border of its
   own vertical, because both halves of a pair arrive at the same point and one
   line into the next box is all that point needs. */
.feeds .bslot::before{
  content:"";position:absolute;left:100%;top:50%;
  width:var(--space-4);border-top:var(--border-width) solid var(--color-border-strong);
}
.feeds .bslot::after{
  content:"";position:absolute;left:calc(100% + var(--space-4));
  width:var(--space-4);height:50%;
  border-left:var(--border-width) solid var(--color-border-strong);
}
/* Odd slots are the top of a pair, so their run goes down, and they draw the
   line into the next box. Even slots come up to meet it. */
.feeds .bslot:nth-child(odd)::after{
  top:50%;border-bottom:var(--border-width) solid var(--color-border-strong);
}
.feeds .bslot:nth-child(even)::after{bottom:50%}

/* No overflow here. The cap is drawn with a ring 1px OUTSIDE its box, and
   clipping the container that holds it shaved that ring off whichever disc sat
   at the edge. The name is the only part that may be cut, and it clips itself. */
.who{
  display:inline-flex;align-items:center;gap:var(--space-2);
  min-width:0;white-space:nowrap;
  font-size:var(--text-sm);
}
.who .swatch{
  width:9px;height:9px;border-radius:2px;flex-shrink:0;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.2);
}
/* A cap, in the actual cap colour. Round, so it is never confused with the
   square team colour beside it, and always ringed so that a white cap is still
   visible on a white row. The column header names it in words as well: the disc
   is a second signal, never the only one. */
.cap{
  width:12px;height:12px;border-radius:50%;flex-shrink:0;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.35), 0 0 0 1px var(--color-border-strong);
}
td .cap{display:inline-block;vertical-align:-2px;margin:0 var(--space-2)}
td[style*="right"] .cap{margin-right:0;margin-left:var(--space-2)}
.who.won{font-weight:var(--weight-semi)}
.who.tbd{color:var(--color-text-faint);font-style:italic}
/* The name is the part that may be any length, so it is the part that gives way.
   The markers keep their size and stay pinned to whichever edge they are on. */
.who .nm{overflow:hidden;text-overflow:ellipsis;min-width:0}
/* Except in a bracket box, where it wraps instead. A table row has a fixed
   height and a neighbouring column to give way to, so an ellipsis there is a
   fair trade; a bracket box has neither, and at 390px it was showing
   "Maastricht Mant..." for five of twelve teams. The box is free to grow
   downwards, so it does. */
.bx .who{white-space:normal}
.bx .who .nm{overflow:visible;text-overflow:clip;overflow-wrap:anywhere}
.who.mirror{flex-direction:row}

/* ---- score boxes -------------------------------------------------------- */
input.score{
  width:2.75rem;height:var(--ctl-h-sm);padding:0 var(--space-1);
  text-align:center;font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  border-radius:var(--radius-sm);
}
input.score:disabled{background:var(--color-surface-sunken);color:var(--color-text-faint)}
.score-cell{padding-left:var(--space-1);padding-right:var(--space-1)}
.table.fixtures td{padding-top:var(--space-1);padding-bottom:var(--space-1)}
tr.dead td{opacity:.5}

/* Fixtures are drawn as one table per round, and a timetable as one per time
   slot, because each carries its own heading. Separate tables size their columns
   from their own contents, so the same column starts at a different place in
   every one of them and a page of fixtures reads as a ragged mess. A fixed
   layout with declared widths is what makes them line up: every table on the
   page then has identical geometry, whatever is in it. */
.table.fixtures,.table.timetable{table-layout:fixed;min-width:46rem}
/* Only the cells that hold a name may be clipped. Putting this on every cell
   also clipped the score cells, which put a stray ellipsis beside every box. */
.table.fixtures td.name,.table.timetable td.name{overflow:hidden;text-overflow:ellipsis}
.table.fixtures .who,.table.timetable .who{max-width:100%}

/* ==========================================================================
   The calendar of tournament days. Six fixed weeks, so it never changes height.
   ========================================================================== */

.cal{
  display:grid;grid-template-columns:repeat(7,minmax(0,1fr));
  border-top:var(--border-width) solid var(--color-border);
}
.cal-head{
  padding:var(--space-2) var(--space-3);
  font-size:var(--text-label);letter-spacing:.08em;text-transform:uppercase;
  font-weight:var(--weight-semi);color:var(--color-text-muted);
  border-bottom:var(--border-width) solid var(--color-border);
  background:var(--color-surface-sunken);
}
.cal-day{
  min-height:6.5rem;padding:var(--space-2);min-width:0;overflow:hidden;
  border-bottom:var(--border-width) solid var(--color-border);
  border-right:var(--border-width) solid var(--color-border);
  display:flex;flex-direction:column;gap:2px;
  transition:background var(--duration) var(--ease);
}
.cal-day:nth-child(7n+7){border-right:0}
.cal-day.out{background:var(--color-surface-sunken);opacity:.6}
.cal-num{
  font-size:var(--text-sm);font-weight:var(--weight-semi);
  color:var(--color-text-muted);align-self:flex-start;
  min-width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;
}
.cal-day.today .cal-num{
  background:var(--color-accent-strong);color:var(--color-on-accent);
  border-radius:var(--radius-pill);
}
.cal-ev{
  display:flex;align-items:baseline;gap:var(--space-2);
  width:100%;min-width:0;text-align:left;padding:2px var(--space-2);
  border:0;border-left:3px solid currentColor;border-radius:3px;
  background:var(--color-surface-sunken);color:var(--color-accent-strong);
  font-family:var(--font-text);font-size:var(--text-sm);line-height:1.35;
  text-decoration:none;overflow:hidden;white-space:nowrap;
}
/* A day that is booked and not laid out yet is still a day you are busy, so it
   is here, in the same shape, saying quietly that it holds no matches. */
.cal-ev.pending{color:var(--color-border-strong)}
.cal-ev.pending .cal-title{color:var(--color-text-muted)}
/* The colour is carried by the left rule. The title itself stays ink. */
.cal-ev .cal-title{
  color:var(--color-text);min-width:0;overflow:hidden;text-overflow:ellipsis;
}
.cal-ev:hover{background:var(--color-accent-quiet)}
.cal-time{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-text-faint);flex-shrink:0}
.cal-more{font-size:var(--text-label);color:var(--color-text-faint);padding-left:var(--space-2)}

/* ==========================================================================
   Timetable slots
   ========================================================================== */

.slot{display:grid;grid-template-columns:5.5rem 1fr;align-items:start;gap:var(--space-3)}
.slot + .slot{border-top:var(--border-width) solid var(--color-border)}
.slot-time{
  padding:var(--space-3) var(--space-4);
  font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-weight:var(--weight-semi);color:var(--color-accent-ink);
  background:var(--color-accent-quiet);align-self:stretch;
}

/* ==========================================================================
   The written walkthrough. One measure, so it reads like a document rather than
   like an app screen that happens to contain paragraphs.
   ========================================================================== */
/* The frame is the app's frame, and the measure is on the reading line.
   Capping the wrap itself at 46rem centred the whole walkthrough inside a
   --page header, so the one page in the app made of paragraphs was also the one
   page whose left edge did not line up with the brand above it. The studio's
   document pages hit this exact wall and moved the 46rem onto the prose; this
   is that same shape, which is where it should have been all along. */
.helpdoc{max-width:var(--page)}
.helpdoc > .viewhead,
.helpdoc > .help-toc,
.helpdoc > .help-sec,
.helpdoc > .help-foot{max-width:46rem}
.help-toc{
  display:flex;flex-wrap:wrap;gap:var(--space-2);
  padding:var(--space-4) 0 var(--space-6);
  border-bottom:var(--border-width) solid var(--color-border);
  margin-bottom:var(--space-8);
}
.help-toc a{
  display:inline-flex;align-items:center;height:var(--ctl-h-sm);padding:0 var(--space-3);
  border-radius:var(--radius-pill);background:var(--color-surface-sunken);
  color:var(--color-accent-ink);text-decoration:none;
  font-size:var(--text-sm);font-weight:var(--weight-medium);
}
.help-toc a:hover{background:var(--color-accent-strong);color:var(--color-on-accent)}
.help-sec{margin:0 0 var(--space-10);scroll-margin-top:calc(var(--header-h) + var(--space-4))}
.help-sec h2{
  font-family:var(--font-display);font-size:var(--text-h2);font-weight:var(--weight-display);
  letter-spacing:var(--tracking-h2);margin:0 0 var(--space-4);
  padding-bottom:var(--space-2);border-bottom:2px solid var(--color-accent);
}
.help-sec p,.help-sec li{color:var(--color-text-muted);line-height:var(--leading-lg)}
.help-sec p{margin:0 0 var(--space-4)}
.help-sec b{color:var(--color-text);font-weight:var(--weight-semi)}
.help-sec ol,.help-sec ul{margin:0 0 var(--space-4);padding-left:var(--space-6)}
.help-sec li{margin-bottom:var(--space-2)}
.help-dl{margin:0 0 var(--space-4);display:grid;gap:var(--space-4)}
.help-dl dt{
  font-family:var(--font-display);font-weight:var(--weight-display);
  color:var(--color-text);margin-bottom:2px;
}
.help-dl dd{margin:0;color:var(--color-text-muted);font-size:var(--text-sm);line-height:var(--leading-sm)}
.help-dl em{color:var(--color-text-faint);font-style:italic}
.help-foot{color:var(--color-text-faint);font-size:var(--text-sm);padding-top:var(--space-6);border-top:var(--border-width) solid var(--color-border)}
.help-foot a{color:var(--color-accent-ink)}

/* The printed document has no place on screen. print.css reveals it. */
#printout{display:none}

/* ==========================================================================
   Motion. Dial 3: feedback only. Every rule here is gated, and there is no
   perpetual animation anywhere in the app.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;
  }
  .btn:active{transform:none}
}

/* ==========================================================================
   Mobile. Every multi-column layout collapses, and the header keeps one line
   by dropping the studio word rather than wrapping.
   ========================================================================== */
@media (max-width:860px){
  .wrap{padding:0 var(--space-4)}
  .door{padding:var(--space-8) 0 var(--space-6)}
  .door img,.door .jc-mark{width:80px;height:80px;margin-bottom:var(--space-4)}
  .does{grid-template-columns:1fr;gap:var(--space-5)}
  .viewhead{align-items:flex-start;flex-direction:column;gap:var(--space-3)}
  .viewhead .spacer{margin-left:0}
  .appfoot .wrap{flex-direction:column;align-items:flex-start;gap:var(--space-3)}
  /* A bracket cannot collapse into one column and still be a bracket, and a
     week cannot have fewer than seven days. Both scroll sideways inside their
     own panel instead, and the page itself never does. */
  .bracket{gap:var(--space-6)}
  .bcol{min-width:12rem}
  .cal{min-width:38rem}
  .panel > .body.flush:has(.cal){overflow-x:auto}
  .slot{grid-template-columns:1fr;gap:0}
  .slot-time{padding:var(--space-2) var(--space-4)}
}
/* The five tabs need about 520px. Sharing a row with the brand and the two
   tool buttons, they were down to 82px of it at phone width: one tab, sliced
   through its badge, with no sign that the other four were a sideways scroll
   away. Below the desk they take a row of their own, the full width of the
   page, and the fade at the right edge says there is more. */
@media (max-width:1023px){
  /* Two rows do not fit in the studio's 68px, and a fixed height here does not
     clip the overflow, it centres it: the brand and the tools were drawn a few
     pixels above the bar's own background. */
  .appbar{height:auto;min-height:var(--header-h)}
  .appbar .wrap{flex-wrap:wrap;row-gap:var(--space-2);padding-top:var(--space-2);padding-bottom:var(--space-2)}
  .appnav{order:3;flex:1 0 100%;margin-left:0;scroll-snap-type:x proximity}
  .appnav a{scroll-snap-align:start}
}
@media (max-width:640px){
  .brand .studio{display:none}
  .appnav a{padding:0 var(--space-3)}
  /* Here the tabs cannot all fit however they are packed, so the right edge
     fades to say the row scrolls. */
  .appnav{
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
  }
}
