.page{
  position:relative;z-index:1;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:24px;
  padding:18px 16px 32px;
}
.wrap{width:100%;max-width:720px;order:0;}
.rail{width:100%;max-width:720px;}
.rail-left{order:1;}
.rail-right{order:2;}
@media (min-width:1400px){
  .page{flex-direction:row;justify-content:center;align-items:flex-start;}
  /* Deliberately NOT sticky. These rails hold every tier, so they are
     always taller than the viewport, and position:sticky on an element
     taller than its scrollport pins to a different edge depending on
     scroll direction - which had NA and EU drifting out of line on the
     way up. */
  .rail{width:372px;flex:0 0 372px;max-width:none;margin-top:-40px;}
  .rail-left{order:-1;}
  .rail-right{order:1;}
  .wrap{order:0;}
}
.title-row{display:flex;align-items:center;gap:12px;margin-bottom:8px;}
#matchPanelsContainer{display:flex;flex-direction:column;gap:16px;}
/* A card, not a full-bleed strip, and still a bar - shrink-wrapped to
   its contents it became a small deformed lozenge. The emptiness was
   never the amount of information, it was being the only thing on the
   page spanning the viewport. The closed contour earns its keep too:
   the urgency pulse needs one to travel around. */
.relink-banner{
  /* Hidden until there is a timer to show; updateRelinkBanner sets
     style.display itself from then on. */
  display:none;
  position:relative;z-index:1;
  width:100%;max-width:720px;
  margin:12px auto 0;padding:8px 22px;border-radius:10px;
  /* Denser, for the same reason the team sides went from 42% to 62%:
     a near-transparent wash puts thin text straight onto the photo. */
  background:linear-gradient(180deg, rgba(44,76,90,.62), rgba(20,34,43,.52));
  -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
  border:1px solid var(--accent-soft);
  border-top-color:rgba(160,230,255,.32);
  box-shadow:
    inset 0 1px 0 rgba(200,240,255,.18),
    inset 0 -1px 0 rgba(0,0,0,.4),
    0 2px 3px rgba(0,0,0,.4),
    0 16px 32px -16px rgba(0,0,0,.85);
}
.relink-inner{
  display:flex;align-items:center;justify-content:center;
}
/* No cap: the two stats share the bar's width evenly through their own
   flex:1, so the bar reads as full rather than as a shelf with a small
   island parked in the middle of it. */
.relink-stat{
  flex:1 1 0;display:flex;flex-direction:column;align-items:center;gap:2px;
  cursor:help;
}
/* Relief here is typographic: labels pushed into the surface, numbers
   lifted off it, same top-lit direction as the cards. */
.relink-stat-title{
  font-size:.66rem;font-weight:700;color:#8d97a6;
  text-transform:uppercase;letter-spacing:.1em;
  text-shadow:0 1px 0 rgba(0,0,0,.55);
}
/* tabular-nums matters more here than anywhere else on the page: these
   digits are replaced every minute, and proportional figures make the
   whole line re-centre itself each time one changes width. Fixed-width
   figures keep a ticking clock still - and cost no height. */
.relink-stat-value{
  font-size:.94rem;color:#f2f6fa;
  font-variant-numeric:tabular-nums;
  text-shadow:0 1px 2px rgba(0,0,0,.6);
}
/* Same split as the team cards: the label names the number, the number
   is the point. NA/EU is a label wearing a number's clothes, so it goes
   down with the rest of them. */
.relink-stat-value .region{color:#8d97a6;font-weight:400;}
.relink-stat-value .time{font-weight:700;color:#f2f6fa;}
/* A groove, not a line: one dark pixel with a lit one beside it is the
   whole trick to making a separator look cut rather than drawn. */
.relink-divider{
  width:2px;height:26px;margin:0 20px;border-radius:1px;
  background:linear-gradient(90deg, rgba(0,0,0,.5), rgba(180,225,245,.13));
}
.relink-stat--primary .relink-stat-title{
  color:var(--accent);
  text-shadow:0 1px 0 rgba(0,0,0,.6);
}
/* The one number on the page that is allowed to glow: it is the
   deadline everything else on the bar is measured against. */
.relink-stat--primary .relink-stat-value{
  font-size:1.18rem;font-weight:700;color:var(--accent);letter-spacing:.2px;
  text-shadow:0 1px 2px rgba(0,0,0,.7), 0 0 14px rgba(127,214,242,.35);
}
@media (max-width:460px){
  .relink-inner{flex-direction:column;gap:8px;}
  .relink-divider{
    width:50%;height:2px;margin:0;
    background:linear-gradient(180deg, rgba(0,0,0,.5), rgba(180,225,245,.13));
  }
}
/* ---- The teams notice ------------------------------------------- */
/* A bar across the very top of the window, edge to edge, sticking there once
   the page scrolls past it. Why a bar rather than a toast, why it stands
   still rather than travelling, and why the surface carries no hue are in
   _source/decisoes-aviso-times.md with the alternatives that lost. The one
   thing here that is not taste is the position: see index.html, where the
   element actually sits, and check-structure.py, which asserts it. */
.teams-notice{
  /* Turned against the real thing rather than reasoned. Width first: the bar
     spans the window, so its contents are not held to the 720px column the
     rest of the page uses - at 1040 the whole sentence fits on one line on a
     desktop, and one line is what keeps the bar shallow. */
  --teams-notice-width:1040px;
  --teams-notice-pad-y:8px;
  --teams-notice-letter:.02em;
  --teams-notice-size:.82rem;

  display:none; /* until updateTeamsNotice sets it to block */
  position:sticky;top:0;z-index:40;
  width:100%;
  /* Symmetric, and that is the reason for the number rather than tidiness.
     46px is clearance for the close button, which is absolutely positioned
     and so takes no space of its own - but .teams-notice-inner below is
     centred with `margin:0 auto`, and auto margins split what is left of the
     CONTENT box. So asymmetric padding leaks straight into the centring: 46
     against 18 put the sentence (46-18)/2 = 14px left of the middle, on a bar
     whose own background is lit at exactly 50% and gives the eye a perfect
     reference for it. The mobile rule at the bottom keeps its asymmetry on
     purpose; see there. */
  padding:0 46px;
  /* Radial rather than a straight sweep down, and that is the part that
     matters: the page's own background is a radial from the top, so a bar
     built the same way belongs to it instead of sitting on it - and the light
     lands where the sentence is, which gives the bar a centre without giving
     it a colour. */
  background:radial-gradient(120% 220% at 50% 0%,
    rgba(38,44,54,.97) 0%, rgba(20,24,30,.97) 55%, rgba(11,13,17,.97) 100%);
  /* No backdrop-filter here, and the absence is the decision. The surface is
     .97 opaque, so three per cent of the backdrop ever showed through, and a
     blur is a GPU pass per frame over whatever moves behind it - here the
     ember canvas, redrawing constantly. An 8px blur was on this bar and was
     removed on 28/09/2026 after looking for the difference and not finding
     it. Same rule this project already reached in css/standings.css: "Opaque
     retires the backdrop-filter too." The other three blurred surfaces keep
     theirs - the relink banner below at .62/.52, the controls, the panels -
     because those are genuinely translucent. */
  border-bottom:1px solid #2c333d;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.05),
    0 8px 24px -12px rgba(0,0,0,.9);
}
.teams-notice-inner{
  /* Two centrings for two halves of one problem: the auto margins centre the
     1040px column in the window, and this centres the sentence inside the
     column - it does not fill it, and the leftover all landed on the right.
     Free on a narrow window, where the paragraph shrinks to the full width
     and there is no space left to distribute. */
  display:flex;align-items:center;justify-content:center;gap:13px;
  width:100%;max-width:var(--teams-notice-width);margin:0 auto;
  padding:var(--teams-notice-pad-y) 0;
}
.teams-notice-mark{
  display:flex;flex-shrink:0;color:var(--muted);
}
/* letter-spacing rather than a bigger size or more padding: the bar is meant
   to be shallow, and tracking is the one way to give a line room
   horizontally without giving it any vertically. Small values only - past
   about .04em a sentence starts reading as a label. */
.teams-notice-text{
  margin:0;
  font-size:var(--teams-notice-size);
  letter-spacing:var(--teams-notice-letter);
  line-height:1.45;color:#eaf1f7;
  text-shadow:0 1px 2px rgba(0,0,0,.45);
}
.teams-notice-text strong{color:#fff;font-weight:700;}
/* The page's two answers, set in the accent and left alone: recognised on the
   way past, not clicked. buildTeamsNotice says why they are neither links nor
   buttons. */
.teams-notice-ref{
  color:var(--accent);font-weight:700;
}
.teams-notice-ref--icon{
  /* Two pixels lower than the 13px shield sat: the box grew by two, and it is
     the mark inside it that has to line up with the sentence, not the box. */
  display:inline-flex;align-items:center;vertical-align:-4px;
}
/* Read out, never seen: the word the shield stands for. The icon is a noun in
   the middle of a sentence, and a screen reader that skips it is left with
   "or open the, beside any NA team" - an instruction with a hole where the
   object goes. Not display:none and not visibility:hidden, which is the whole
   point: both take the text out of the accessibility tree as well. nowrap
   because a clipped box one pixel wide would otherwise wrap the phrase into a
   column of single letters, and some screen readers read that as letters. */
.teams-notice-spoken{
  position:absolute;width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);
  white-space:nowrap;
}
/* Findable without being loud, which took two tries - a faint glyph at 65%
   was too easy to miss, and a lit circle with a rim was a lozenge parked on
   the end of the bar. So no rim and no fill at rest, a target 30px square for
   the finger, and a soft square of light under it on hover. The stroke is
   drawn rather than typed; buildTeamsNotice says why a × character cannot be
   centred in a box. */
.teams-notice-close{
  position:absolute;top:50%;right:8px;transform:translateY(-50%);
  width:30px;height:30px;padding:0;
  display:flex;align-items:center;justify-content:center;
  background:none;border:none;border-radius:7px;
  box-shadow:none;text-shadow:none;
  color:#9aa4b2;
  cursor:pointer;
  transition:background .15s ease, color .15s ease;
}
.teams-notice-close:hover{
  background:rgba(255,255,255,.07);color:#fff;filter:none;
}
/* button:active would depress it and stamp the page's inset shadows on a
   transparent square. It outranks the rule above on its own. */
.teams-notice-close:active{transform:translateY(-50%);box-shadow:none;}
/* A bar that looks trim on a desktop can take a fifth of a phone's screen.
   The tracking goes first, because it is the one thing here that costs height
   on a narrow window. */
@media (max-width:600px){
  .teams-notice{
    --teams-notice-letter:0;
    --teams-notice-size:.78rem;
    /* Still asymmetric here, where the base rule is not. Symmetric would mean
       38px on both sides instead of 38 and 12, which is 26px of a phone's
       width spent on a centring nobody can see: at this size the sentence
       fills the line and wraps, so there is no free space for centring to
       move. The 26px is another chance of one more line, which is the thing
       this whole block is tuned against. */
    padding:0 38px 0 12px;
  }
  .teams-notice-close{width:28px;height:28px;right:5px;}
}

/* .36, down from .45, and lower is the point: the crest carries its own
   highlight now, so a halo on top of it reads as haze. The footer copy has no
   filter at all and is the reference for how much is enough. */
.title-row svg{flex-shrink:0;filter:drop-shadow(0 0 5px rgba(140,224,255,.36));}
h1{
  font-family:Cambria,Georgia,'Times New Roman',serif;
  font-size:1.7rem;margin:0;letter-spacing:1.5px;text-transform:uppercase;
  background:linear-gradient(100deg,#e7ebf0 20%,var(--accent) 55%,#e7ebf0 85%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* The colour scanning across the top of the page. It looks the same as
   it always did; what changed is who draws it.

   It used to animate background-position, which is the one property
   here the compositor cannot take: every frame, for as long as the tab
   was open, the browser repainted the whole strip on the main thread.
   Measured at 4x CPU throttle it was about 150ms of Paint every two
   seconds, on a page that was otherwise doing nothing.

   A transform can be handed to the GPU, so the strip is painted once and
   then only slid. The gradient moves to a child wide enough to slide:
   600% holds two of the 300%-wide tiles, and travelling one tile lands
   the pattern exactly where it started, which is what keeps the seam
   invisible. Same speed as before - it covers half the old distance in
   half the old time, which is why 7s reads as 3.5s here. */
.header-rule{
  position:relative;overflow:hidden;
  height:2px;border-radius:2px;margin:0 0 22px;opacity:.55;
}
.header-rule::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:600%;
  background:linear-gradient(90deg,var(--red),var(--accent),var(--blue),var(--green),var(--red));
  background-size:50% 100%;
  animation:rule-scan 3.5s linear infinite;
}
@keyframes rule-scan{0%{transform:translateX(0);}100%{transform:translateX(-50%);}}
/* The one time the scan stands down: while the banner is raising an
   alarm. The banner already refuses to run both of its own pulses at
   once - two things pulsing read as decoration rather than as a warning
   - and a colour scanning across the top of the page is a third. It is
   the only one of them that means nothing, so it is the one that gives
   way. The sibling combinator reaches it because the banner and .page
   are both children of <body>, which is why this needs no JavaScript. */
.relink-banner.is-urgent ~ .page .header-rule::before,
.relink-banner.is-relink-week ~ .page .header-rule::before,
.relink-banner.is-rebuild ~ .page .header-rule::before,
.relink-banner.is-lockout ~ .page .header-rule::before{animation:none;}
.subtitle{color:var(--muted);font-size:.92rem;margin-bottom:24px;line-height:1.5;max-width:720px;}
