/* ============================================================================
   timetable.css — CHAMPETOETERS & FRIENDS
   One job: who plays when and where. Padel only, 12:30 → 20:00.

   Rules this file must keep (BRIEF §0):
     · no glass panes; one hairline per row; a row is time · baan · names
     · one accent (--tt-ball), spent only on FINALE and on "Nu bezig"
     · desktop has no controls; mobile has exactly one (the court switcher)
     · nothing blurred ever moves (§4.2); no background-clip: text
   ========================================================================= */

.tt-section {
  --tt-paper:  244 247 251;
  --tt-haze:   124 153 182;
  --tt-ball:   198 220 99;
  --tt-ink:    13 22 55;

  /* Letterspaced caps lose a lot to antialiasing: small text needs a lifted
     tint AND ≥12px AND weight. */
  --tt-micro:  212 228 246;
  --tt-dim:    rgb(var(--tt-paper) / .78);
  --tt-rule:   rgb(var(--tt-haze) / .22);

  --tt-serif: var(--font-display, "Playfair Display", "Didot", "Bodoni 72", "Times New Roman", serif);
  --tt-sans:  var(--font-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif);

  /* The tail is both the section's bottom padding and the height of .tt-dusk,
     so the ramp into the DJ bill lives entirely in empty space: the sticky
     venue panel is contained by .tt-body and therefore stops exactly where
     the ramp starts. Keep the two in step — it is a real coupling. */
  --tt-tail: clamp(72px, 8vw, 116px);   /* the footer sits close under the sheet (client) */

  /* How far BEFORE the end of the schedule the sticky venue panel lets go —
     set on .tt-body with the rest of the layout (a sticky box is constrained
     by its containing block minus its own margins; the bottom margin on the
     panel is cancelled again on the schedule, buying an early release without
     adding a pixel of empty page). */

  position: relative;
  isolation: isolate;
  padding: clamp(56px, 9vw, 128px) 0 var(--tt-tail);
  color: rgb(var(--tt-paper));
  font-family: var(--tt-sans);
  -webkit-font-smoothing: antialiased;
  background-color: #0D1637;
  overflow: clip;
}

/* Top: the hero now sits directly above, and it ends a few values LIGHTER than
   this section's flat navy — measured (19,29,58) against (13,22,55). So this is
   a lift that carries the hero's last light a little way into the sheet and
   dies out before the first match, not the near-black band it had to be when
   the DJ bill's dark tail was above it. */
/* Top: the sheet follows the BILL, which dissolves its own bottom to
   rgb(20 30 62) (.ln__sky). The plate starts on that same handoff tone and
   lets go over its height, so the boundary is a blend, not a line. */
.tt-plate {
  position: absolute; inset: 0 0 auto; z-index: 0;
  height: clamp(220px, 30vw, 380px);
  pointer-events: none;
  background-image: linear-gradient(180deg, rgb(20 30 62) 0%, rgb(20 30 62 / .45) 45%, rgb(20 30 62 / 0) 100%);
}

/* Bottom: the sheet is now the LAST section, so the tail ramps to the footer's
   own top colour — #1E294E = rgb(30 41 78), the value shell.css paints — and
   the two meet without a band or a step. */
.tt-dusk {
  position: absolute; inset: auto 0 0; z-index: 0;
  height: var(--tt-tail);
  pointer-events: none;
  background-image:
    linear-gradient(180deg, rgb(30 41 78 / 0) 0%, rgb(30 41 78 / .5) 58%, rgb(30 41 78) 100%);
}

/* Above the opaque sticky surfaces, or they read as untextured panels. */
.tt-grain { z-index: 3; opacity: .2; }
.tt-section > .u-container { position: relative; z-index: 2; }

/* ---------------------------------------------------------------- header */

.tt-head { margin-bottom: clamp(30px, 4.6vw, 60px); }
.tt-eyebrow {
  margin: 0 0 clamp(12px, 1.8vw, 18px);
  font-size: clamp(12px, 3.1vw, 13px);
  font-weight: 700;
  letter-spacing: .22em;
  color: rgb(var(--tt-micro));
}
.tt-title {
  /* u-display's wide haze glow was tuned for a busy photographic ground; on
     this section's flat navy it renders as a smudge around the glyphs. */
  text-shadow: 0 2px 14px rgb(3 7 22 / .5);
  margin: 0;
  font-size: clamp(2.5rem, 8.4vw, 5rem);
  letter-spacing: .028em;
  line-height: .92;
}
.tt-title__a { display: block; }
.tt-title__b {
  display: block; margin-left: .08em;
  font-size: clamp(1.3rem, 4.4vw, 2.6rem); letter-spacing: .07em;
}

/* ------------------------------------------------------------ body layout */

/* ONE layout at every width: the venue panel is a full-width landscape strip
   pinned above the schedule, and the schedule scrolls under it. It was a
   portrait side column on desktop until the resting 3D became the fixed
   south view (courts3d.js REST_AZ) — that shot is a wide horizontal band, and
   in a 292px portrait column it floated tiny between two slabs of empty
   tarmac. The client called it: same panel-on-top arrangement as the phone,
   landscape at every size.

   Side effect worth knowing: the five schedule columns now get the whole
   1180px container instead of sharing it with the panel, so the 1200px agenda
   breakpoint (below) is comfortably safe rather than exactly measured.

   Flex, not grid: a sticky grid item is trapped in its own grid area and has
   nothing to travel through. A flex item's containing block is the flex
   container, so the panel pins for the length of .tt-body and releases at
   the end of the section on its own. */
.tt-body {
  --tt-3d-h: clamp(240px, 34vh, 320px);
  /* Enough lead that the panel is already moving before the DJ bill can
     appear at the bottom of the screen: panel height + lead + tail must
     clear the viewport. Measured at 390x844. */
  --tt-release: clamp(300px, 40vh, 380px);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
}
.tt-body > * { min-width: 0; }
.tt-switch   { order: 1; display: none; }   /* desktop shows all five courts */
.tt-venue {
  order: 2;
  position: sticky;
  top: 0;
  z-index: 4;                 /* the schedule AND its sticky headers pass behind */
  /* Opaque and exactly as wide as the rows, so nothing can show beside it.
     The padding is the clear margin above and below: without it a sliver of
     a row rides along the panel's edge as it scrolls under. */
  padding: 10px 0 12px;
  background: #0D1637;
  /* The early release (see --tt-release). The margin is taken straight back
     off the schedule below it, so .tt-body is exactly as tall as before and
     nothing on the page moves — only the sticky constraint rectangle gets
     shorter. Both halves must always change together. */
  margin-bottom: var(--tt-release);
}
.tt-gridwrap { order: 3; min-width: 0; margin-top: calc(-1 * var(--tt-release)); }
/* NO fade ramp under the panel. A 40px gradient in the page colour used to sit
   here so a row leaving under the panel faded instead of being sliced — but a
   row spends that whole 40px UNDER it, which paints the top of white glyphs
   dark grey and makes the line hard to read on the way out. A clean edge
   against an opaque sticky surface is what every sheet does; that wins. */
/* Keyboard focus must keep the panel's full height clear of itself. */
.tt-m,
.tt-row { scroll-margin-top: calc(var(--tt-3d-h) + 34px); }
/* A little more height on a desktop viewport — same landscape strip, room
   for the labels to breathe. Complements the max-width:1200px agenda query. */
@media (min-width: 1200.02px) {
  .tt-body {
    --tt-3d-h: clamp(280px, 38vh, 420px);
    /* NO early release on desktop. The lead is a phone measurement (panel +
       tail must clear 390x844 before the footer arrives), and desktop is the
       one width where the court names exist: .tt-hcell pins against the
       panel's bottom edge, but its sticky rectangle is the TABLE, which runs
       on for the whole release. Release the panel early and the last screen
       shows the panel sliding up away from a header row still nailed to
       --tt-3d-h + 22px — the names hanging in open navy. With the lead at 0
       the panel's rectangle ends where the table does and the two let go
       together; the header slips behind the panel (z 3 under 4) as it goes,
       exactly as the rows do. */
    --tt-release: 0px;
  }
}

/* --------------------------------------------------------------- the grid */

.tt-grid { width: 100%; border-collapse: collapse; table-layout: fixed; }
.tt-col--time { width: 58px; }

/* Sticky court names — the sheet is tall. Never blurred, so a scroll-linked
   position is free (BRIEF §4.2/§4.4). */
.tt-hcell {
  /* Under the venue panel, which is sticky above the table (z-index 4): the
     headers pin against its bottom edge; 22px is the panel's own padding. */
  position: sticky; top: calc(var(--tt-3d-h) + 22px); z-index: 3;
  padding: 14px 10px 12px;
  text-align: left;
  font-family: var(--tt-serif);
  font-size: clamp(1rem, 1.3vw, 1.22rem);
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgb(var(--tt-paper) / .95);
  background-color: #0D1637;               /* the page colour: only the rule shows */
  box-shadow: inset 0 -1px 0 var(--tt-rule);
  transition: color .18s ease;
}
.tt-hcell--time { padding-left: 0; }
.tt-hcell.is-hot { color: rgb(var(--tt-ball)); }
/* No ramp here either — same reason as .tt-venue above: 16px of page colour
   over a row is 16px of dimmed white text, and the hairline under the court
   names is a cleaner edge to disappear behind than a grey wash. */

/* One hairline per time and nothing else — it is how the eye tracks from the
   time across to the right court. */
.tt-time,
.tt-cell { border-bottom: 1px solid rgb(var(--tt-haze) / .14); vertical-align: top; }

.tt-time {
  padding: 16px 14px 16px 0;
  text-align: left;
  font-size: 1rem; font-weight: 600; letter-spacing: .02em;
  color: rgb(var(--tt-paper) / .95);
  white-space: nowrap;
}
.tt-cell { padding: 10px 0 12px; }

/* ------------------------------------------------------------- a match
   Not a card. The button exists only so the 3D lights up on hover/tap; it must
   never look like something you are required to press. */

.tt-m {
  display: block; width: 100%;
  min-height: 44px;
  padding: 6px 8px 7px;
  margin: 0;
  border: 0; border-radius: 10px;
  background: transparent;
  color: inherit; font-family: inherit; text-align: left;
  cursor: pointer;
  transition: background-color .16s ease;
}
.tt-m:hover,
.tt-m.is-hot { background: rgb(var(--tt-paper) / .07); }
.tt-m:focus-visible { outline: 2px solid rgb(var(--tt-ball)); outline-offset: 1px; }

.tt-m__court { display: none; }        /* desktop: the column header says it */

/* The type of match, on the cell itself. Quiet: it is the third thing you read
   after the time and the names, and on a full sheet it repeats a lot. */
.tt-m__kind {
  display: block;
  font-family: var(--tt-serif);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: rgb(var(--tt-micro));
  line-height: 1.4;
  margin-bottom: 3px;
}

.tt-m__tie { display: block; }
.tt-m__n {
  display: block;
  font-size: .875rem; font-weight: 600; letter-spacing: .005em;
  line-height: 1.35;
  color: rgb(var(--tt-paper));
  overflow-wrap: anywhere;
}
/* "Vrije plaats" and an unresolved knockout slot. Client: not italic. Same
   face and size as a real name, lighter weight, dimmer — a quiet entry, never
   a decorative one. Alpha stays high enough that .is-done still clears 4.5:1. */
.tt-m__n.is-open,
.tt-m__n.is-tbd {
  font-weight: 400;
  color: rgb(var(--tt-paper) / .78);
}
.tt-m__b { display: flex; align-items: baseline; gap: 6px; }
/* Client: "the vs in the courts is just a weird font v". It was a lone italic
   Didone letter between two lines of sans. Now: same face as the names, one
   step smaller, and a word instead of a glyph. */
/* .76 is the floor: under .is-done's .68 it still measures 4.8:1 on pixels. */
.tt-m__v {
  flex: none;
  font-family: inherit; font-style: normal;
  font-size: .78rem; font-weight: 500; letter-spacing: .01em;
  color: rgb(var(--tt-paper) / .76);
}
.tt-m__b .tt-m__n { flex: 1 1 auto; min-width: 0; }

/* the day itself — the only other place the accent is spent.
   One device, shared with the DJ bill's "Speelt nu" (.ln__live): a flat
   bordered pill with a dot, in the accent, never blurred and never animated.
   Bare letterspaced text broke over two lines at 390px and squeezed the names
   beside it; a pill on its own line under the tie cannot. */
.tt-m__live {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 7px;
  padding: 4px 11px;
  border: 1px solid rgb(var(--tt-ball) / .5);
  border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: rgb(var(--tt-ball));
  white-space: nowrap;
}
.tt-m__live-dot {
  flex: none;
  width: 6px; height: 6px; border-radius: 999px;
  background: rgb(var(--tt-ball));
  box-shadow: 0 0 9px rgb(var(--tt-ball) / .55);
}
/* Played and not yet scored: dim the row, it is behind us. .68 keeps it over
   4.5:1 on the section ground. */
.tt-m.is-done { opacity: .68; }

/* ---------------------------------------------------------------- the score
   A result is content, not a badge (BRIEF: content before style). One extra
   line under the tie — same column as the names at both viewports — set in
   tabular figures so the games line up down the sheet. No box, no tint, no
   rule, no accent: the accent is reserved for FINALE and "Nu bezig".

   A scored row is NOT dimmed as a whole: the winner stays lit and the loser
   steps back, which says more than fading both. Measured on rendered pixels
   against #0D1637: the loser at .62 is 6.9:1, the score at .70 is 8:1. */
.tt-m.is-done.has-score { opacity: 1; }

.tt-m__score {
  display: block;
  margin-top: 4px;
  font-size: .8rem; font-weight: 500; letter-spacing: .06em;
  color: rgb(var(--tt-paper) / .7);
  white-space: nowrap;
}

.tt-m__n.is-win  { font-weight: 700; color: rgb(var(--tt-paper)); }
.tt-m__n.is-lost { font-weight: 400; color: rgb(var(--tt-paper) / .62); }
/* An unresolved or open slot never carries emphasis it has not earned. */
.tt-m__n.is-open.is-win,
.tt-m__n.is-tbd.is-win { font-weight: 400; color: rgb(var(--tt-paper) / .78); }

/* ----------------------------------------------------------- headings
   One label per phase, four in total, never stamped on a row. */

.tt-heading {
  padding: clamp(34px, 4vw, 52px) 0 clamp(9px, 1.2vw, 13px);
  font-family: var(--tt-serif);
  font-size: 13px; font-weight: 400;
  letter-spacing: .26em; text-transform: uppercase;
  color: rgb(var(--tt-micro));
}
/* POULES gets the same air above it as KNOCK-OUT and HALVE FINALES. It used to
   be the one exception (padding-top: 0, because it opens the sheet), which read
   as the heading being glued to the court names. */

.tt-heading--final {
  font-size: clamp(1.5rem, 3.4vw, 2.4rem);
  letter-spacing: .3em;
  color: rgb(var(--tt-ball));
  padding-bottom: clamp(12px, 1.6vw, 18px);
}

/* --------------------------------------------------------- 3D / plan */

/* One height rule at every width: the strip the sticky panel is allowed
   (--tt-3d-h, set with the body layout above). ~287px at 390x844, so ~500px
   of schedule stays in view under it. */
.tt-venue__stage {
  position: relative; width: 100%;
  height: var(--tt-3d-h);
  min-height: 0;
  border-radius: var(--r-xl, 26px); overflow: hidden;
  background: linear-gradient(180deg, #16265A, #0C142F);
  border: 1px solid rgb(var(--tt-haze) / .18);
}
.tt-venue__plan,
.tt-venue__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.tt-venue__canvas { z-index: 1; }
/* visibility, not only opacity: the flat plan carries court numbers, and an
   opacity:0 <svg> still hands its text to the accessibility tree. */
.tt-venue[data-mode="3d"] .tt-venue__plan { opacity: 0; visibility: hidden; }
.tt-venue[data-mode="plan"] .tt-venue__canvas { opacity: 0; }

.pl { width: 100%; height: 100%; }
/* The indoor hall. Deliberately quieter than a court — it is the reason Baan 4
   and 5 sit off on their own, not a thing you can pick. */
.pl-hall {
  fill: rgb(var(--tt-paper) / .05);
  stroke: rgb(var(--tt-haze) / .3); stroke-width: .3;
  stroke-dasharray: 3 2; vector-effect: non-scaling-stroke;
}
.pl-face {
  fill: rgb(58 90 151 / .4);
  stroke: rgb(var(--tt-haze) / .55); stroke-width: .34; vector-effect: non-scaling-stroke;
  transition: fill .18s ease, stroke .18s ease;
}
.pl-net { stroke: rgb(var(--tt-paper) / .4); stroke-width: .3; vector-effect: non-scaling-stroke; }
/* Sized in viewBox units, i.e. METRES: 5.2 is a 5.2 m tall numeral, about half a
   court's width, which is as large as it can be and still sit inside the court it
   labels. It is small on screen now that the viewBox spans the whole 170 m site,
   and it cannot be fixed by growing the glyph — this is the WebGL-failure
   fallback, and its job is which-court-is-where, not legibility at a glance. */
.pl-num {
  font-family: var(--tt-serif); font-size: 5.2px; letter-spacing: .06em;
  fill: rgb(var(--tt-paper) / .55); text-anchor: middle; dominant-baseline: central;
  transition: fill .18s ease;
}
.pl-court.is-active .pl-face { fill: rgb(var(--tt-ball) / .3); stroke: rgb(var(--tt-ball)); }
.pl-court.is-active .pl-num { fill: rgb(var(--tt-ball)); }

/* ======================================================================
   NARROW — 390px up to 1200px. The sheet becomes a time-first agenda: a time,
   then the courts that have a match at that time. The ARIA roles in the markup
   keep the table semantics through display:block.

   The threshold was 900px while there were three court columns. Five need
   ~161px each to hold a team name on one line, and 5 x 161 + the time column +
   the venue panel does not fit inside 1200px however the space is divided —
   below that the grid was breaking names mid-word. So the agenda now covers the
   whole band down from 1200, which includes a landscape iPad. Nothing in here
   was written for 390px only; the panel geometry is in vh and the rows are a
   plain list, so it stretches without a second set of tuning.
   ==================================================================== */

@media (max-width: 1200px) {
  /* The panel-above-the-schedule layout is now the DEFAULT at every width —
     this block only swaps the five-column table for the time-first agenda
     and shows the court switcher. */

  /* the one control — six segments now: Alle + five banen. Six full "Baan n"
     labels do not fit 390px, so the buttons print courts.json's `short` ("B1")
     and carry the full name in aria-label. Equal columns, so "Alle" gets the
     same 1/6 as the rest and the pill stays a pill. */
  .tt-switch {
    display: grid; grid-template-columns: repeat(6, 1fr); gap: 2px;
    padding: 3px;
    border: 1px solid var(--tt-rule);
    border-radius: 999px;
  }
  .tt-seg {
    min-height: 44px; padding: 6px 2px;
    border: 0; border-radius: 999px; background: transparent;
    color: rgb(var(--tt-paper) / .8); cursor: pointer;
    font: 600 .8rem/1.2 var(--tt-sans); letter-spacing: .04em;
    transition: color .16s ease, background-color .16s ease;
  }
  .tt-seg[aria-pressed="true"] { background: rgb(var(--tt-paper)); color: rgb(var(--tt-ink)); }
  .tt-seg:focus-visible { outline: none; box-shadow: var(--focus-ring); }

  .tt-grid, .tt-grid thead, .tt-grid tbody, .tt-grid tr, .tt-grid th, .tt-grid td { display: block; }
  .tt-grid { table-layout: auto; }
  .tt-grid thead { display: none; }

  .tt-row { margin: 0 0 20px; }
  .tt-row.is-empty { display: none; }

  .tt-time {
    padding: 0 0 8px;
    margin: 0 0 4px;
    border-bottom: 1px solid var(--tt-rule);
    font-size: 1.28rem; font-weight: 600;
  }

  .tt-cell { padding: 0; border-bottom: 0; }
  .tt-grid .tt-cell:empty,
  .tt-grid .tt-cell.is-off { display: none; }

  /* time · baan · names — one tap target per match, 56px tall */
  .tt-m {
    display: flex; align-items: baseline; gap: 12px;
    min-height: 56px;
    padding: 9px 10px 10px;
    margin-inline: -10px;
    width: calc(100% + 20px);
  }
  .tt-m.is-off { display: none; }
  .tt-m__court {
    display: block; flex: 0 0 4.6rem;
    font-family: var(--tt-serif);
    font-size: 13px; font-weight: 400; letter-spacing: .14em; text-transform: uppercase;
    color: rgb(var(--tt-micro));
    line-height: 1.5;
  }
  /* one court chosen: repeating its name thirteen times is noise */
  .tt-gridwrap.is-single .tt-m__court { display: none; }
  /* On the phone the row is a flex line — the type rides with the names, not
     as a block above them, or every row grows a third line. */
  .tt-m__kind { margin-bottom: 1px; font-size: 10.5px; }
  .tt-m__tie { flex: 1 1 auto; min-width: 0; }
  .tt-m__n { font-size: .95rem; }

  .tt-heading { padding: clamp(26px, 6vw, 34px) 0 12px; }
  .tt-heading--final { padding-bottom: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .tt-m, .tt-hcell, .pl-face, .pl-num { transition: none; }
}

/* Safety net only: if tokens.css/glass.css ever fail to load these keep the
   section legible. :where() = zero specificity, so the real foundation wins. */
:where(.tt-section) { background-color: #0D1637; color: #F4F7FB; }
:where(.u-container) { width: 100%; max-width: 1292px; margin-inline: auto; padding-inline: 20px; }
:where(.u-tabular) { font-variant-numeric: tabular-nums; }
:where(.u-sr-only) {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
