/* =====================================================================
   GoDartsPro : shared game styles
   /wp-content/themes/dart/assets/css/gdp-game.css

   Everything here is game agnostic and prefixed gdp-. A new game includes
   this file and gets the same scoreboard, keypad, chips, overlays and
   result table without restyling anything.

   Layout is scoped under .gdp. Only the tokens are global, because the throw
   overlay renders outside the game container.
   ===================================================================== */

/* Tokens sit on :root, not on .gdp. The throw overlay is appended to
   document.body so any game can use it without markup, and a variable
   scoped to .gdp would resolve to nothing out there. */
:root{
  /* Brand ground, type and amber, straight from the guidelines. Amber is
     the one highlight: active player, active seat, chips, the checkout, the
     darts on the board. Green is kept for go actions only, so the two never
     compete for the same meaning. */
  --gdp-bg:#0a0a0a; --gdp-panel:#141414; --gdp-panel2:#1d1d1d; --gdp-line:#2b2b2b;
  --gdp-ink:#ffffff; --gdp-muted:#9b9b9b;
  --gdp-accent:#ffa400; --gdp-accent-ink:#241000;
  --gdp-win:#3ddc84; --gdp-bust:#ff5a52;
  --gdp-go:#2c8a5a; --gdp-go-hi:#37a56d;
  /* Structural lines: the ring around the board, the keypad edge, the score
     field. Light enough to read across a room, cool enough not to compete
     with amber. */
  --gdp-frame:rgba(255,255,255,.4);
  --gdp-radius:14px;
  /* Oswald carries the whole interface: scores, keys, labels, buttons.
     The note face is only for small running text, where a condensed
     display face gets hard to read. */
  --gdp-font:'Oswald',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --gdp-font-note:'Helvetica Neue',Helvetica,Arial,sans-serif;

  /* How much of the photograph the tint holds back. The setup screen has
     paragraphs to read over it, gameplay has a handful of large figures,
     so the two want different amounts. */
  --gdp-tint-hi:rgba(8,8,8,.90);
  --gdp-tint-lo:rgba(8,8,8,.87);
  /* The divider itself. Full strength on the setup screen, where it is the
     brand signature on an otherwise plain view. */
  --gdp-divider:var(--gdp-accent);
  /* Fixed so the device list can hang exactly off the bottom of the badge
     instead of guessing where that is. */
  --gdp-badge-h:34px;
  /* The Your stats tab: its height before rotation, which is also how far
     it has to sit in from the border to end up flush against it. */
  --gdp-tab-h:34px;
}

.gdp{
  color:var(--gdp-ink);
  font-family:var(--gdp-font);
  background:var(--gdp-bg);
  /* The gap above the frame is padding here, not a margin on the wrapper.
     A margin would collapse straight through this element, which has no top
     border or padding of its own, and the space would open up outside the
     black background and show the page behind it. */
  padding-top:20px;
  /* Also stops any margin inside the game escaping the same way. */
  display:flow-root;
}
.gdp *,.gdp *::before,.gdp *::after{box-sizing:border-box;}
/* The outer container. container-main-graphic is the platform class, so
   whatever the theme paints on it applies here too. Only the frame is set
   from this file. */
/* The floor stops the frame collapsing when the keypad is hidden during
   the opponent's visit, which otherwise makes the whole page jump. */
.gdp-wrap{max-width:1170px;margin:0 auto;padding:22px 20px 30px;position:relative;
  min-height:700px;
  /* A neutral hairline rather than amber. The theme's own graphic behind
     the game is blue, and amber on blue was fighting it. */
  border:1px solid rgba(255,255,255,.24);border-radius:var(--gdp-radius);}
.gdp .is-hidden{display:none !important;}

/* ---------- type ---------- */
.gdp-h1{font-family:var(--gdp-font);font-size:30px;font-weight:600;margin:0;line-height:1;}
.gdp-eyebrow{font-family:var(--gdp-font);font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--gdp-muted);}
.gdp-label{font-family:var(--gdp-font);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--gdp-muted);}
.gdp-hint{font-family:var(--gdp-font-note);font-weight:300;font-size:12.5px;
  color:var(--gdp-muted);line-height:1.5;letter-spacing:.01em;}

/* ---------- autotrack, from the shared viewpart ----------
   That markup lives inside the game wrapper so the Scolia badge anchors to
   it, which means it inherits the colour and face set on .gdp. Its own
   theme classes carry the styling, so those two are handed back. The
   z-index keeps the badge and the correction panel above the setup
   background and the score panels. */
/* The status badge is notched into the top border rather than floating over
   it. Sharing the page's own black means the amber line stops at the badge
   and starts again after it, which is what makes it read as part of the
   frame instead of a chip dropped on top of it.

   The viewpart sets colours inline, on a shared file used by every other
   game, so those are the one place !important is warranted here. */
.gdp .autotrack-status-wrapper{
  position:absolute;
  top:0;
  right:26px;
  transform:translateY(-50%);
  z-index:1200;
  margin:0;
  width:auto;
  height:var(--gdp-badge-h);
  display:flex;
  align-items:center;
  padding:0 13px;
  background:var(--gdp-bg);
  border:1px solid var(--gdp-accent);
  border-radius:20px;
  line-height:1;
  box-shadow:none;
}
.gdp .autotrack-status-wrapper table{width:auto !important;margin:0;}
.gdp .autotrack-status-wrapper td{padding:0;border:0;vertical-align:middle;}
.gdp .autotrack-status-wrapper a{text-decoration:none;}
.gdp .autotrack-status-wrapper .js-autotrack-status-label{
  color:var(--gdp-accent) !important;
  font-family:var(--gdp-font);
  letter-spacing:.12em;
}
.gdp .autotrack-status-wrapper .js-autotrack-list-btn{
  color:var(--gdp-muted) !important;
}
.gdp .autotrack-status-wrapper .js-autotrack-list-btn:hover{
  color:var(--gdp-ink) !important;
}
.gdp .autotrack-status-wrapper .js-autotrack-list{
  border-left-color:var(--gdp-line) !important;
}

/* The device list hangs from the badge, so it starts just below the line.

   The viewpart styles this panel inline, as a white box with white borders,
   which is why every rule that has to beat one carries !important. Those
   are only where an inline style exists: the panel box itself, the three
   hairlines, and two hard coded text colours. */
.gdp .autotrack-list-dropdown-container{
  position:absolute;
  /* The badge is centred on the top edge, so its underside is half its
     height below that. One pixel of overlap so the two read as joined
     rather than as a panel that happens to be nearby. */
  top:calc(var(--gdp-badge-h) / 2 - 1px);
  right:26px;
  margin:0;
  z-index:1199;

  /* The panel is drawn here, on the outer element, rather than on the div
     the viewpart styles inline. That inner div was clipping its own bottom
     border, and no amount of overriding a border on an element that is
     cutting itself off will show it. Styling the parent sidesteps the
     whole argument: this element has no inline styles to beat and nothing
     inside it to clip against. */
  min-width:224px;
  padding:13px 15px 14px;
  border:1px solid var(--gdp-accent);
  border-radius:12px;
  background:rgba(12,12,12,.97);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  box-shadow:0 18px 40px -12px rgba(0,0,0,.8);
  overflow:visible;
}

/* Open, the two become one shape: the badge squares off along the bottom
   and the panel squares the corner it meets. */
.gdp.is-scolia-menu-open .autotrack-status-wrapper{
  border-radius:20px 20px 0 0;
}
.gdp.is-scolia-menu-open .autotrack-list-dropdown-container{
  border-radius:12px 0;
}

/* The inner div keeps its inline white box, so it is emptied out. */
.gdp .autotrack-list-dropdown-container > div{
  min-width:0 !important;
  padding:0 !important;
  margin:0 !important;
  border:0 !important;
  border-radius:0 !important;
  background:none !important;
  box-shadow:none !important;
  overflow:visible !important;
}

/* Type, matching the badge above it. */
.gdp .autotrack-list-dropdown-container table{width:100% !important;margin:0;}
.gdp .autotrack-list-dropdown-container td{padding:0;border:0;vertical-align:top;}
.gdp .autotrack-list-dropdown-container .app-header-s,
.gdp .autotrack-list-dropdown-container .text-color{
  font-family:var(--gdp-font);
  color:var(--gdp-ink) !important;
}
/* The heading takes the accent, the way the badge label does. */
.gdp .autotrack-list-dropdown-container table td:first-child{
  color:var(--gdp-accent) !important;
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  padding-bottom:2px;
}
.gdp .autotrack-list-dropdown-container a{text-decoration:none;}
.gdp .autotrack-list-dropdown-container a .text-color{
  color:var(--gdp-muted) !important;font-size:15px !important;padding:0 !important;}
.gdp .autotrack-list-dropdown-container a:hover .text-color{color:var(--gdp-accent) !important;}

/* The hairlines between devices. */
.gdp .autotrack-list-dropdown-container div[style*="border-bottom"]{
  border-bottom-color:var(--gdp-line) !important;
}

.gdp .autotrack-list-dropdown-wrapper{padding-top:8px !important;}
.gdp .autotrack-list-dropdown-container .device-list-item{
  border-radius:7px;padding:5px 7px;margin-left:-7px;margin-right:-7px;
  transition:background .15s ease;
}
.gdp .autotrack-list-dropdown-container .device-list-item:hover{
  background:rgba(255,255,255,.07);
}
/* Two colours the viewpart sets inline: the tick, and the leave action. */
.gdp .autotrack-list-dropdown-container .fa-check{color:var(--gdp-win) !important;}
.gdp .autotrack-list-dropdown-container .js-select-device{color:#ff7a72 !important;}
.gdp .autotrack-list-dropdown-container .js-select-device:hover{color:var(--gdp-bust) !important;}

@media(max-width:700px){
  .gdp .autotrack-status-wrapper,
  .gdp .autotrack-list-dropdown-container{ right:14px; }
  .gdp .autotrack-status-wrapper{ padding:3px 10px; }
}

.gdp .autotrack-list-dropdown-container,
.gdp .autotrack-multiple-instances-container,
.gdp .score-correction-container,
.gdp .dart-detail-container,
.gdp .dart-retrieve-container{
  font-family:revert;
  color:revert;
  z-index:1200;
}

/* The three tracked dart boxes sit under the scoreboard. Fixed against the
   game wrapper rather than the theme's own offset, because this template
   puts the scores higher than the older ones do. */
.gdp .dart-detail-container{
  top:230px;
}

/* ---------- the ground under every screen ----------
   The photograph, the brand divider and the tint sit on the container
   rather than on the setup screen, so the game keeps the same ground
   instead of falling back to the theme's own graphic. It also puts the
   divider on the box its geometry was worked out for.

   The stop is a position along the rotated gradient axis, not a height, so
   it is not the number it looks like. At roughly 1170 x 700 a stop of 40%
   puts the seam at 92% height on the left edge and 38% on the right.
   Taller boxes push the seam up: recompute rather than nudging by eye.
   Line width 0.3% of the axis is the brand's 3px. */
.gdp-wrap{
  background-image:
    linear-gradient(-18deg, transparent 0 39.7%, var(--gdp-divider) 39.7% 40%, transparent 40%),
    linear-gradient(-18deg, var(--gdp-tint-hi) 0 40%, var(--gdp-tint-lo) 40%),
    url('/wp-content/themes/dart/images/2026/260623-start-main-photo-2.webp');
  background-size:100% 100%, 100% 100%, cover;
  background-position:center, center, right top;
  background-repeat:no-repeat;
}

/* In play the photograph comes forward. There is far less to read here
   than on the setup screen, and the score carries its own shadow. */
/* The result screen has as much to read as the setup does, and the
   divider was cutting through it at full strength. */
.gdp-wrap.is-over{
  --gdp-tint-hi:rgba(8,8,8,.90);
  --gdp-tint-lo:rgba(8,8,8,.87);
  --gdp-divider:rgba(255,164,0,.45);
}

.gdp-wrap.is-playing{
  --gdp-tint-hi:rgba(8,8,8,.76);
  --gdp-tint-lo:rgba(8,8,8,.71);
  /* Quieter in play. The tint is lighter here, which would otherwise make
     the line read louder against everything sitting on top of it. */
  --gdp-divider:rgba(255,164,0,.5);
}

/* Panels float over the photograph instead of blanking it out. */
.gdp-screen-setup .gdp-card{background:rgba(18,18,18,.88);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);}
/* The introduction gets a panel of its own, at a lower opacity than the
   option cards. Enough to lift the words clear of the divider, little
   enough that the line still reads as running on behind them. */
.gdp-screen-setup .gdp-intro{
  background:rgba(12,12,12,.78);
  backdrop-filter:blur(3px);
  -webkit-backdrop-filter:blur(3px);
  border:1px solid rgba(255,255,255,.06);
  border-radius:var(--gdp-radius);
  padding:20px 22px 22px;
}
.gdp-screen-setup .gdp-intro p,
.gdp-screen-setup .gdp-intro dd{text-shadow:0 1px 6px rgba(0,0,0,.75);}

@media(max-width:900px){
  /* Narrower and taller, so the same seam needs a lower stop. */
  .gdp-wrap{
    background-image:
      linear-gradient(-18deg, transparent 0 27.9%, var(--gdp-divider) 27.9% 28.2%, transparent 28.2%),
      linear-gradient(-18deg, var(--gdp-tint-hi) 0 28.2%, var(--gdp-tint-lo) 28.2%),
      url('/wp-content/themes/dart/images/2026/260623-start-main-photo-2-mobile.webp');
  }
}

@media(max-width:700px){
  .gdp-wrap{
    background-image:
      linear-gradient(-18deg, transparent 0 22.3%, var(--gdp-divider) 22.3% 22.7%, transparent 22.7%),
      linear-gradient(-18deg, var(--gdp-tint-hi) 0 22.7%, var(--gdp-tint-lo) 22.7%),
      url('/wp-content/themes/dart/images/2026/260623-start-main-photo-2-mobile.webp');
  }
}

/* ---------- setup layout ---------- */
/* Options on the left, what the options mean on the right. Half each on a
   desktop, stacked below 900px with the form first, because on a phone the
   reading matter should not stand between a player and the start button. */
.gdp-setup{display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:start;}
.gdp-setup-main{min-width:0;}

.gdp-intro{min-width:0;}
.gdp-intro h2{font-family:var(--gdp-font);font-size:13px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--gdp-accent);margin:0 0 8px;font-weight:500;}
.gdp-intro h2:not(:first-child){margin-top:24px;}
.gdp-intro p{font-family:var(--gdp-font-note);font-weight:300;font-size:13.5px;
  line-height:1.65;color:var(--gdp-muted);margin:0 0 10px;}
/* ---------- an unfinished match ----------
   Amber edged rather than a warning colour: nothing has gone wrong, there
   is simply a game still open. */
.gdp-resume{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  flex-wrap:wrap;
  background:rgba(26,19,5,.92);
  border:1px solid var(--gdp-accent);
  border-radius:var(--gdp-radius);
  padding:15px 18px;margin-bottom:14px;
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
}
.gdp-resume-body{min-width:0;}
.gdp-resume-title{font-family:var(--gdp-font);font-size:17px;color:var(--gdp-accent);}
.gdp-resume-line{font-family:var(--gdp-font);font-size:13.5px;color:var(--gdp-muted);
  margin-top:3px;}
.gdp-resume-actions{display:flex;gap:8px;flex-wrap:wrap;}
.gdp-resume-actions .gdp-btn{padding:10px 20px;font-size:14px;}

/* Each group of tabs stands on its own, so a second set can be added to
   the introduction without the two switching together. */
.gdp-tabgroup{margin-bottom:6px;}

/* The bot row holds a chip row and then whichever detail belongs to the
   choice, so its body stacks instead of running along one line. */
.gdp-set-stack{flex-direction:column;align-items:stretch;gap:12px;}
.gdp-bot-detail{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
.gdp-bot-detail input[type=range]{flex:1;min-width:150px;}

/* ---------- tabs in the introduction ---------- */
.gdp-tabs{display:flex;gap:2px;flex-wrap:wrap;
  border-bottom:1px solid var(--gdp-line);margin-bottom:12px;}
.gdp-tab{font-family:var(--gdp-font);font-size:13.5px;background:none;border:0;
  color:var(--gdp-muted);padding:8px 11px;cursor:pointer;
  border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;}
.gdp-tab:hover{color:var(--gdp-ink);}
.gdp-tab.is-on{color:var(--gdp-accent);border-bottom-color:var(--gdp-accent);}
.gdp-tab:focus-visible{outline:2px solid var(--gdp-win);outline-offset:-2px;}
.gdp-tab-panel{display:none;}
.gdp-tab-panel.is-on{display:block;}

.gdp-intro-list{margin:0;}
.gdp-intro-list dt{font-family:var(--gdp-font);font-size:15px;color:var(--gdp-ink);
  font-weight:500;margin-top:12px;}
.gdp-intro-list dt:first-child{margin-top:0;}
.gdp-intro-list dd{font-family:var(--gdp-font-note);font-weight:300;font-size:13.5px;
  line-height:1.6;color:var(--gdp-muted);margin:3px 0 0;padding-left:12px;
  border-left:2px solid var(--gdp-line);}

@media(max-width:900px){
  .gdp-setup{grid-template-columns:1fr;gap:22px;}
  .gdp-intro{padding-left:0;}
}

/* ---------- surfaces ---------- */
.gdp-card{background:var(--gdp-panel);border:1px solid var(--gdp-line);
  border-radius:var(--gdp-radius);padding:14px 16px;margin-bottom:10px;}

/* A compact settings row: label on the left, controls on the right. */
.gdp-set{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:9px 0;border-bottom:1px solid var(--gdp-line);}
.gdp-set:last-child{border-bottom:0;}
.gdp-set > .gdp-label{flex:0 0 96px;}
.gdp-set-body{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:1;}
@media(max-width:560px){
  .gdp-set{align-items:flex-start;flex-direction:column;gap:6px;}
  .gdp-set > .gdp-label{flex:none;}
}

/* ---------- disclosure ---------- */
/* Folded away, independently of whether the row belongs to this opponent
   at all. Two separate reasons to be out of sight, so two separate
   classes: one switch cannot serve both without them fighting. */
.gdp .is-folded{display:none;}

.gdp-label-stack{display:flex;flex-direction:column;align-items:flex-start;gap:5px;}
.gdp-fold{background:none;border:0;padding:0;cursor:pointer;
  font-family:var(--gdp-font);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gdp-accent);
  display:inline-flex;align-items:center;gap:6px;opacity:.85;}
.gdp-fold:hover{opacity:1;}
.gdp-fold i{font-size:9px;transition:transform .18s;}
.gdp-fold[aria-expanded="true"] i{transform:rotate(180deg);}

.gdp-more{background:none;border:0;color:var(--gdp-muted);cursor:pointer;font-family:var(--gdp-font);
  font-size:12px;letter-spacing:.14em;text-transform:uppercase;padding:10px 0 2px;
  display:flex;align-items:center;gap:7px;}
.gdp-more:hover{color:var(--gdp-ink);}
.gdp-more i{transition:transform .18s;}
.gdp-more[aria-expanded="true"] i{transform:rotate(90deg);}

/* ---------- chips ---------- */
.gdp-chips{display:flex;flex-wrap:wrap;gap:5px;}
.gdp-chip{font-family:var(--gdp-font);font-size:13.5px;line-height:1;background:var(--gdp-panel2);
  border:1px solid var(--gdp-line);color:var(--gdp-ink);border-radius:8px;padding:8px 12px;
  cursor:pointer;transition:background .15s,border-color .15s,color .15s;}
.gdp-chip:hover{border-color:#4a4a4a;}
.gdp-chip.is-on{background:var(--gdp-accent);border-color:var(--gdp-accent);
  color:var(--gdp-accent-ink);font-weight:600;}
.gdp-chip.is-locked{opacity:.45;cursor:not-allowed;}
.gdp-chip:focus-visible{outline:2px solid var(--gdp-win);outline-offset:2px;}

/* preset chips carry a small remove control */
.gdp-preset{display:inline-flex;align-items:center;gap:7px;}
.gdp-preset-x{opacity:.5;font-size:11px;}
.gdp-preset-x:hover{opacity:1;}

/* ---------- fields ---------- */
/* Every text bearing input, listed by type. A rule that names only some of
   them leaves the rest on browser defaults, which is a white box in the
   middle of a dark form. */
.gdp input[type=text],
.gdp input[type=number],
.gdp input[type=email],
.gdp input[type=password],
.gdp input[type=tel],
.gdp input[type=search],
.gdp select{
  background:var(--gdp-panel2);border:1px solid var(--gdp-line);color:var(--gdp-ink);
  border-radius:8px;padding:7px 10px;font-family:var(--gdp-font);font-size:14px;height:36px;}
.gdp input:focus,.gdp select:focus{outline:none;border-color:var(--gdp-accent);}
.gdp input::placeholder{color:#6b6b6b;opacity:1;}
.gdp-num{width:76px;text-align:center;}

/* Native select, restyled. The arrow is drawn here because the built in
   one cannot be recoloured, and appearance:none removes it. */
.gdp-select{position:relative;display:inline-block;}
.gdp-select::after{content:"";position:absolute;right:12px;top:50%;
  width:7px;height:7px;margin-top:-5px;pointer-events:none;
  border-right:2px solid var(--gdp-muted);border-bottom:2px solid var(--gdp-muted);
  transform:rotate(45deg);}
.gdp-select:hover::after{border-color:var(--gdp-ink);}
.gdp .gdp-select select{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  font-family:var(--gdp-font);font-size:19px;font-variant-numeric:tabular-nums;
  height:42px;padding:0 34px 0 14px;min-width:110px;
  background:var(--gdp-panel2);border:1px solid var(--gdp-line);
  border-radius:9px;color:var(--gdp-ink);cursor:pointer;}
.gdp .gdp-select select:hover{border-color:#4a4a4a;}
.gdp .gdp-select select:focus{outline:none;border-color:var(--gdp-accent);}
.gdp .gdp-select select option{background:#141414;color:#fff;font-size:15px;}

/* Names rather than numbers, so it sits at the chip size instead of the
   larger figure size the game select uses. */
.gdp .gdp-select-sm select{font-size:13.5px;height:36px;min-width:150px;padding-right:30px;}
.gdp .gdp-select-sm select option{font-size:13.5px;}
.gdp-select-sm::after{right:11px;width:6px;height:6px;margin-top:-4px;}
.gdp input[type=range]{accent-color:var(--gdp-accent);height:26px;flex:1;min-width:130px;}
/* Toggle switch. A bare checkbox reads as a form field rather than a
   control, and people were not spotting that it was clickable. The native
   input is kept for keyboard and screen reader behaviour and only the
   painted track is swapped in. */
.gdp-switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer;font-family:var(--gdp-font);
  font-size:14px;user-select:none;-webkit-user-select:none;}
.gdp-switch input{position:absolute;opacity:0;width:1px;height:1px;margin:0;}
.gdp-switch-track{flex:0 0 auto;position:relative;width:46px;height:26px;border-radius:13px;
  background:#2f2f2f;border:1px solid var(--gdp-line);transition:background .18s,border-color .18s;}
.gdp-switch-knob{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;
  background:var(--gdp-muted);transition:transform .2s cubic-bezier(.16,1,.3,1),background .18s;}
.gdp-switch input:checked + .gdp-switch-track{background:var(--gdp-accent);
  border-color:var(--gdp-accent);}
.gdp-switch input:checked + .gdp-switch-track .gdp-switch-knob{
  transform:translateX(20px);background:var(--gdp-accent-ink);}
.gdp-switch input:focus-visible + .gdp-switch-track{outline:2px solid var(--gdp-win);
  outline-offset:2px;}
.gdp-switch:hover .gdp-switch-track{border-color:#4a4a4a;}
.gdp-switch-label{line-height:1.25;}

.gdp-check{display:inline-flex;align-items:center;gap:7px;cursor:pointer;font-size:13.5px;}

/* ---------- buttons ---------- */
.gdp-btn{font-family:var(--gdp-font);font-size:15px;border-radius:10px;padding:11px 20px;cursor:pointer;
  border:1px solid var(--gdp-line);background:var(--gdp-panel2);color:var(--gdp-ink);}
.gdp-btn:hover{border-color:#4a4a4a;}
.gdp-btn-primary{background:var(--gdp-accent);border-color:var(--gdp-accent);
  color:var(--gdp-accent-ink);font-weight:600;font-size:16px;padding:13px 28px;width:100%;}
.gdp-btn-ghost{background:transparent;}
.gdp-icon{background:none;border:0;font-family:var(--gdp-font);color:var(--gdp-muted);cursor:pointer;font-size:16px;padding:6px;}
.gdp-icon:hover{color:var(--gdp-ink);}

/* =====================================================================
   Scoreboard

   One number owns the screen, because the player reading it is standing
   two and a half metres away. Both players stay visible in a strip above
   it, small, since a bot or a guest still has a score worth a glance.
   ===================================================================== */
.gdp-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:0 2px 10px;flex-wrap:wrap;}
.gdp-bar-rules{font-family:var(--gdp-font);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gdp-muted);}
.gdp-bar-actions{display:flex;gap:6px;align-items:center;}

/* ---------- both players, compact ---------- */
.gdp-strip{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px;}
.gdp-strip-seat{display:flex;align-items:center;gap:13px;flex-wrap:wrap;
  background:var(--gdp-panel);border:1px solid var(--gdp-line);
  border-left:4px solid var(--gdp-line);
  border-radius:10px;padding:9px 13px;transition:border-color .2s,background .2s,opacity .2s;}
.gdp-strip-seat.is-active{border-color:var(--gdp-accent);background:#1a1305;}

/* The second seat is the first one reflected: tally, score, name, then the
   photograph on the outside edge. Mirroring rather than repeating puts both
   players' faces on the outside of the pair and both scores toward the
   middle, so the two totals sit next to each other and can be compared at a
   glance. The accent bar moves to the outer edge with everything else. */
.gdp-strip-seat.is-mirrored{
  flex-direction:row-reverse;
  border-left-width:1px;
  border-right:4px solid var(--gdp-line);
  text-align:right;
}
.gdp-strip-seat.is-mirrored.is-active{border-right-color:var(--gdp-accent);}
.gdp-strip-seat.is-idle{opacity:.55;}
/* The member's own photograph, in a ring that picks up the highlight when
   it is their turn. Two shadows: a dark hairline to separate the ring from
   a light photo, and a soft drop so the circle sits on the panel rather
   than in it. */
.gdp-strip-avatar{
  flex:0 0 auto;
  width:56px;height:56px;
  border-radius:50%;
  background:#1d1d1d center/cover no-repeat;
  border:2px solid #3a3a3a;
  box-shadow:0 0 0 1px rgba(0,0,0,.65), 0 2px 8px rgba(0,0,0,.5);
  transition:border-color .2s,box-shadow .2s;
}
.gdp-strip-seat.is-active .gdp-strip-avatar{
  border-color:var(--gdp-accent);
  box-shadow:0 0 0 1px rgba(0,0,0,.65), 0 0 14px rgba(255,164,0,.35);
}

.gdp-strip-name{font-family:var(--gdp-font);font-size:clamp(19px,2.2vw,28px);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.gdp-strip-seat.is-active .gdp-strip-name{color:var(--gdp-accent);}
.gdp-strip-score{font-family:var(--gdp-font);font-size:clamp(26px,2.6vw,34px);font-weight:600;line-height:1;
  font-variant-numeric:tabular-nums;}
.gdp-strip-tally{font-family:var(--gdp-font);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gdp-muted);white-space:nowrap;}
.gdp-strip-tally b{font-size:clamp(19px,2.4vw,26px);color:var(--gdp-ink);
  font-variant-numeric:tabular-nums;}
.gdp-strip-seat.is-active .gdp-strip-tally b{color:var(--gdp-accent);}
.gdp-strip-tally em{font-style:normal;margin-left:8px;}

/* ---------- score left, keypad right ---------- */
/* auto, not a fixed track: with autotracking the keypad is display none, and
   a fixed column would keep reserving its width and push everything left. */
.gdp-play{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:18px;align-items:start;}
@media(max-width:991px){
  /* Keypad drops below the score, which is what fits a phone. */
  .gdp-play{grid-template-columns:1fr;gap:12px;}
  .gdp-pad{margin:0 auto;}
}

.gdp-focus{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:12px;
  align-items:start;}
.gdp-rail-mirror{width:clamp(78px,11vw,124px);}
.gdp-focus-main{min-width:0;text-align:center;}

/* White, not amber. On the blue graphic behind the game amber loses more
   contrast than it gains attention, and the shadow gives it an edge over
   whatever part of the photograph it lands on. */
.gdp-big{font-family:var(--gdp-font);font-weight:600;
  font-size:clamp(92px,20vw,240px);
  line-height:.9;letter-spacing:-.03em;color:#fff;
  text-shadow:0 6px 34px rgba(0,0,0,.85), 0 1px 3px rgba(0,0,0,.6);
  font-variant-numeric:tabular-nums;margin:2px 0 6px;}
.gdp-big.is-idle{color:var(--gdp-muted);}

/* A leg ending, a bust, or the score standing between legs. All three
   take the place of the running score for a moment, because that is the
   thing being looked at and putting them anywhere else means looking away
   at exactly the wrong time. */
.gdp-big.is-moment{animation:gdpMoment .5s cubic-bezier(.18,1.5,.4,1);}
@keyframes gdpMoment{
  0%   {transform:scale(.55);opacity:0;}
  60%  {transform:scale(1.06);opacity:1;}
  100% {transform:scale(1);opacity:1;}
}
.gdp-big.is-bust{color:var(--gdp-bust);}
.gdp-big.is-legscore{color:#fff;letter-spacing:.02em;}
.gdp-moment-note{font-family:var(--gdp-font);font-size:clamp(14px,2.4vw,20px);
  letter-spacing:.18em;text-transform:uppercase;color:var(--gdp-muted);
  margin-top:-4px;}

/* Placeholders until there is artwork. Both are sized off the score they
   stand in for, so they arrive at the same weight. */
.gdp-symbol{display:block;font-size:clamp(72px,16vw,190px);line-height:1;}
.gdp-symbol.is-skull{color:var(--gdp-bust);
  text-shadow:0 0 34px rgba(255,90,82,.5);}
.gdp-symbol.is-trophy{color:var(--gdp-accent);
  text-shadow:0 0 40px rgba(255,164,0,.55);}

/* ---------- a burst, on a leg won ---------- */
.gdp-spark-layer{position:absolute;left:0;right:0;top:0;bottom:0;
  pointer-events:none;overflow:hidden;z-index:1187;}
.gdp-spark{position:absolute;left:50%;top:58%;
  width:7px;height:7px;border-radius:50%;
  background:var(--gdp-accent);
  box-shadow:0 0 10px 2px rgba(255,164,0,.7);
  opacity:0;
  animation:gdpSpark var(--life) cubic-bezier(.12,.72,.3,1) var(--wait) forwards;
}
/* Up and out, then falling back, which is what a firework does and what a
   straight radial burst conspicuously does not. */
@keyframes gdpSpark{
  0%   {transform:translate(-50%,-50%) scale(.4);opacity:0;}
  12%  {opacity:1;}
  70%  {transform:translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1);opacity:1;}
  100% {transform:translate(calc(-50% + var(--dx) * 1.15),
                            calc(-50% + var(--dy) + var(--fall))) scale(.3);opacity:0;}
}
@media(prefers-reduced-motion:reduce){ .gdp-spark{display:none;} }

/* ---------- score history for the leg ---------- */
.gdp-rail{width:clamp(78px,11vw,124px);}
.gdp-rail-head{font-family:var(--gdp-font);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--gdp-muted);padding-bottom:6px;
  border-bottom:1px solid var(--gdp-line);margin-bottom:6px;}
.gdp-rail-head b{font-size:16px;color:var(--gdp-ink);}
/* Small figures, so they get their own ground rather than relying on the
   tint to keep the divider off them. */
.gdp-rail-list{list-style:none;margin:0;padding:4px;
  background:rgba(8,8,8,.55);border-radius:8px;}
.gdp-rail-list:empty{background:none;padding:0;}
.gdp-rail-row{display:flex;align-items:baseline;gap:6px;padding:4px 6px;border-radius:6px;
  font-family:var(--gdp-font);font-variant-numeric:tabular-nums;line-height:1.1;}
.gdp-rail-row .no{font-size:10px;color:#5a5a5a;width:14px;flex:0 0 14px;}
.gdp-rail-row .sc{font-size:19px;color:var(--gdp-ink);flex:1;text-align:right;}
.gdp-rail-row .left{font-size:12px;color:var(--gdp-muted);width:34px;text-align:right;}
.gdp-rail-row.is-big .sc{color:var(--gdp-accent);}
.gdp-rail-row.is-bust .sc{color:var(--gdp-bust);}
/* The last two visits can still be corrected, so they invite a tap. */
.gdp-rail-row.is-editable{cursor:pointer;background:rgba(255,255,255,.04);}
.gdp-rail-row.is-editable:hover{background:rgba(255,164,0,.14);}

/* ---------- the checkout line ----------
   Sits under the big score. The route is the most actionable thing on the
   screen so it takes the highlight; the negative message is plain white and
   nearly as large, because it is read from the same distance. */
.gdp-checkout-bar{text-align:center;margin:0 auto 8px;min-height:58px;
  display:flex;flex-direction:column;justify-content:center;}
.gdp-checkout-who{font-family:var(--gdp-font);font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gdp-muted);margin-bottom:2px;}
/* Hidden but still taking its line, so the column below does not move up
   into the space when there is no checkout to name. */
.gdp-checkout-who.is-hidden{visibility:hidden;}
.gdp-checkout-value{font-family:var(--gdp-font);font-size:clamp(30px,5.4vw,46px);
  line-height:1.05;font-weight:600;letter-spacing:.05em;color:var(--gdp-accent);}
.gdp-checkout-value.is-none{color:#fff;font-size:clamp(26px,4.4vw,38px);
  letter-spacing:.04em;
  /* Present from the first visit so the layout never shifts, but faint
     while a checkout is a long way off. */
  opacity:.22;transition:opacity .35s ease;}
.gdp-checkout-value.is-none.is-near{opacity:.9;}

/* ---------- where the tracked dart boxes are moved to ---------- */
.gdp-dartslot{margin-top:4px;}
/* Above the banner. It sweeps behind the tracked darts rather than across
   them, so the scores stay readable while it passes. */
.gdp .dart-detail-container{position:relative;z-index:1185;
  top:auto;left:auto;right:auto;
  width:100%;margin:0;padding-top:20px;}
/* Nearly solid. These sit over the divider and the photograph, and a
   score has to be read at a glance, so the line is allowed through as a
   hint rather than across the middle of the number. */
.gdp .dart-detail{
  background:rgba(9,18,13,.90);
  border:1px solid var(--gdp-win);
  border-radius:10px;
  padding:8px 4px;
  backdrop-filter:blur(4px);
  -webkit-backdrop-filter:blur(4px);
}
.gdp .js-dart-detail-score{color:var(--gdp-win) !important;}
.gdp .js-dart-detail-hit{color:var(--gdp-muted) !important;}

@media(max-width:600px){
  /* The mirror stays on a phone. Narrowing both sides costs less than
     letting the score sit off centre, and three digits still fit. */
  .gdp-rail,
  .gdp-rail-mirror{width:62px;}
  .gdp-strip{gap:6px;}
  .gdp-strip-seat{padding:7px 10px;gap:7px;}
  .gdp-strip-avatar{width:38px;height:38px;}
  .gdp-strip-name{font-size:16px;}
  .gdp-strip-score{font-size:22px;}
  .gdp-strip-tally{font-size:10px;}
  .gdp-big{font-size:clamp(76px,23vw,132px);}
  .gdp-rail-row .sc{font-size:16px;}
  .gdp-rail-row .left{width:28px;font-size:11px;}
}

/* =====================================================================
   Keypad
   ===================================================================== */
/* Translucent rather than a solid panel, so the ground behind the game
   carries on through the keypad instead of being blanked out by it. */
/* The keypad and the undo beneath it, as one column, so the button stays
   centred on the pad rather than on whatever space is left. */
.gdp-pad-col{display:flex;flex-direction:column;align-items:center;min-width:0;}

/* Red, labelled, and given room. It used to be an icon in the match bar,
   where it was both easy to miss and easy to hit by accident. Forty pixels
   of gap is deliberate: this undoes a score, and it should not sit close
   enough to ENTER to be caught on the way past. */
.gdp-undo{
  margin-top:40px;
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--gdp-font);font-size:16px;letter-spacing:.06em;
  text-transform:uppercase;
  padding:12px 26px;border-radius:10px;cursor:pointer;
  color:var(--gdp-bust);
  background:rgba(255,90,82,.12);
  border:1px solid rgba(255,90,82,.55);
  transition:background .15s ease,border-color .15s ease,color .15s ease;
}
.gdp-undo:hover{background:rgba(255,90,82,.22);border-color:var(--gdp-bust);}
.gdp-undo:active{background:rgba(255,90,82,.32);}
.gdp-undo i{font-size:15px;}

/* Where it goes when a board is scoring and there is no keypad: under the
   tracked darts, near the bottom edge. */
.gdp-undo-slot{display:flex;justify-content:center;}
.gdp-undo-slot .gdp-undo{margin-top:34px;}

@media(max-width:600px){
  .gdp-undo{margin-top:28px;padding:11px 22px;font-size:15px;}
  .gdp-undo-slot .gdp-undo{margin-top:24px;}
}

.gdp-pad{background:rgba(0,0,0,.6);border:1px solid var(--gdp-frame);
  border-radius:var(--gdp-radius);padding:13px;width:390px;max-width:100%;}
/* Not an input. There is nothing to type into and a caret blinking over
   the score only invites people to tap it. The value is held in JavaScript
   and the keyboard is read at document level, which also means the keypad
   cannot lose focus to anything else on the page. */
.gdp-display{background:var(--gdp-bg);border:1px solid var(--gdp-frame);border-radius:10px;
  height:62px;display:flex;align-items:center;justify-content:center;
  margin-bottom:9px;padding:0 8px;position:relative;}

.gdp-display-value{
  font-family:var(--gdp-font);
  font-size:44px;
  line-height:1;
  color:var(--gdp-ink);
  font-variant-numeric:tabular-nums;
  letter-spacing:.04em;
  user-select:none;-webkit-user-select:none;
  pointer-events:none;
}
/* The waiting zero was nearly invisible. It is the thing a player looks at
   to know the pad is theirs, so it reads as dim rather than as absent. */
.gdp-display-value.is-empty{color:#7b8ea2;}

/* Pinned right, while the score stays centred over the middle column. */
.gdp-finish{position:absolute;right:8px;top:50%;transform:translateY(-50%);
  background:var(--gdp-go);border:1px solid var(--gdp-go-hi);color:#fff;
  font-family:var(--gdp-font);font-size:17px;font-weight:600;letter-spacing:.02em;
  padding:8px 17px;border-radius:8px;cursor:pointer;line-height:1.15;white-space:nowrap;}
.gdp-finish:hover{background:var(--gdp-go-hi);}
.gdp-finish:active{background:#48bd80;}
.gdp-finish:focus-visible{outline:2px solid var(--gdp-win);outline-offset:2px;}

.gdp-keys{display:grid;grid-template-columns:.78fr 1fr 1fr 1fr .78fr;gap:6px;}
.gdp-key{font-family:var(--gdp-font);font-size:28px;padding:16px 0;
  border-radius:10px;background:var(--gdp-panel2);border:1px solid var(--gdp-line);
  color:var(--gdp-ink);cursor:pointer;font-variant-numeric:tabular-nums;
  transition:background .1s;}
.gdp-key:active{background:var(--gdp-accent);color:var(--gdp-accent-ink);}

.gdp-key-speed{font-size:19px;padding:16px 2px;background:#151515;color:var(--gdp-muted);}
.gdp-key-speed:hover{color:var(--gdp-ink);}
.gdp-key-speed:active{background:var(--gdp-accent);color:var(--gdp-accent-ink);}

.gdp-key-go{background:var(--gdp-go);border-color:var(--gdp-go);color:#fff;font-weight:600;
  font-size:16px;letter-spacing:.08em;}
.gdp-key-go:active{background:var(--gdp-go-hi);color:#fff;}

/* The zero key doubles as a 180 while the field is empty, because no score
   is ever entered with a leading zero. */
.gdp-key-dual.is-180{
  background:linear-gradient(160deg,#f6e27a 0%,#d9a938 45%,#b8862a 100%);
  border-color:#e6c65c;color:#2a1e00;font-weight:700;font-size:26px;}
.gdp-key-dual.is-180:active{background:#f6e27a;color:#2a1e00;}

/* ---------- recent scores, tap to correct ---------- */
.gdp-recent{text-align:center;margin:0 auto 10px;}
.gdp-recent-label{font-family:var(--gdp-font);font-size:10px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gdp-muted);display:block;margin-bottom:6px;}
.gdp-recent-list{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;}
.gdp-recent-chip{display:inline-flex;align-items:center;gap:9px;font-family:var(--gdp-font);
  background:var(--gdp-panel2);border:1px solid var(--gdp-line);border-radius:9px;
  padding:7px 13px;color:var(--gdp-ink);cursor:pointer;transition:border-color .15s;}
.gdp-recent-chip:hover{border-color:var(--gdp-accent);}
.gdp-recent-chip .who{font-size:12px;color:var(--gdp-muted);max-width:96px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;}
.gdp-recent-chip .val{font-size:21px;font-variant-numeric:tabular-nums;line-height:1;}
.gdp-recent-chip .val.is-bust{color:var(--gdp-bust);font-size:14px;}
.gdp-recent-chip i{font-size:11px;color:var(--gdp-muted);}
.gdp-recent-chip:hover i{color:var(--gdp-accent);}
/* The visit that ended a leg is shown for context but cannot be retyped:
   changing it would unwind the leg and set structure behind it. Undo is the
   right tool there, and it is one tap away. */
.gdp-recent-chip.is-locked{cursor:default;opacity:.5;}
.gdp-recent-chip.is-locked:hover{border-color:var(--gdp-line);}
.gdp-recent-chip.is-locked:hover i{color:var(--gdp-muted);}

/* ---------- modal ---------- */
/* Above the stats panel, which fills the frame at 1400. A dialog opened
   from inside that panel has to sit over it, not under. */
.gdp-modal{position:fixed;inset:0;z-index:1500;display:flex;align-items:center;
  justify-content:center;padding:16px;background:rgba(6,6,6,.86);
  font-family:var(--gdp-font);color:var(--gdp-ink);}
.gdp-modal-panel{background:var(--gdp-panel);border:1px solid var(--gdp-accent);
  border-radius:18px;padding:16px;width:100%;max-width:430px;}
.gdp-modal-head{text-align:center;margin-bottom:12px;}
.gdp-modal-title{display:block;font-size:20px;}
.gdp-modal-sub{display:block;font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--gdp-muted);margin-top:2px;}
.gdp-modal-panel .gdp-pad{background:none;border:0;padding:0;max-width:none;}
.gdp-modal-actions{margin-top:12px;text-align:center;}

/* ---------- prompt ---------- */
.gdp-prompt{background:var(--gdp-panel);border:1px solid var(--gdp-win);border-radius:var(--gdp-radius);
  padding:18px;text-align:center;max-width:420px;margin:0 auto;}
.gdp-prompt h3{font-family:var(--gdp-font);font-size:19px;margin:0 0 2px;}
.gdp-prompt p{font-family:var(--gdp-font);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--gdp-muted);
  margin:0 0 13px;}
.gdp-prompt-btns{display:flex;gap:8px;justify-content:center;}
.gdp-prompt-btns button{font-family:var(--gdp-font);font-size:23px;min-width:60px;padding:13px 0;
  border-radius:10px;background:var(--gdp-panel2);border:1px solid var(--gdp-win);color:var(--gdp-ink);
  cursor:pointer;}
.gdp-prompt-btns button:hover{background:var(--gdp-win);color:#1c2200;}

/* =====================================================================
   Dartboard and the throw overlay
   ===================================================================== */
.gdp-board{width:100%;height:auto;display:block;
  /* Slow enough to read as a camera move rather than a jump. */
  transition:transform .7s cubic-bezier(.32,.72,.24,1);}
@media(prefers-reduced-motion:reduce){ .gdp-board{transition:none;} }
/* The board never draws outside its own box. Clipping the board's own
   container rather than the wrapper matters: the wrapper also holds the
   callouts, and clipping those would cut the labels short on darts near
   the rim.

   Always on, not only while zoomed. Toggling it left a window during the
   move where the board was already growing and the clip was not yet in
   force, which is how a zoom leaked over the rest of the panel. Nothing is
   clipped at rest, since the board exactly fills this box. */
.gdp-throw-board{overflow:hidden;}

/* The opponent's remaining score, in the top right corner where the name
   used to be. Large, because it is the only number worth reading while
   somebody else throws. */
.gdp-throw-remaining-value{
  display:block;font-family:var(--gdp-font);font-weight:600;
  font-size:clamp(46px,10vw,88px);line-height:.88;
  color:#fff;letter-spacing:-.03em;font-variant-numeric:tabular-nums;
  text-shadow:0 3px 22px rgba(0,0,0,.95), 0 1px 4px rgba(0,0,0,.8);
}
.gdp-board-frame{stroke:var(--gdp-frame);stroke-width:2;}
.gdp-board-number{fill:var(--gdp-frame);}

/* Above everything in the frame. The tracked dart boxes and the banner
   both sit in the 1180s so they can clear each other, and at 1000 this
   backdrop was underneath both of them: the boxes rendered on top of the
   board while the opponent was throwing. */
.gdp-throw{position:fixed;inset:0;z-index:1300;font-family:var(--gdp-font);
  color:var(--gdp-ink);display:flex;align-items:center;
  justify-content:center;padding:18px;background:rgba(6,9,13,.82);
  opacity:0;pointer-events:none;transition:opacity .22s ease;}
.gdp-throw.is-open{opacity:1;pointer-events:auto;}

/* The board is a circle in a square, so both top corners of its box are
   empty. The face goes in one and the name in the other, which lets the
   board fill the whole panel and still leaves the photograph large.

   The width is bounded by viewport height as well, because the board is
   square: on a short laptop screen the panel narrows rather than running
   off the bottom. */
.gdp-throw-panel{background:var(--gdp-panel);border:1px solid var(--gdp-line);border-radius:18px;
  padding:16px;width:100%;max-width:min(600px, 76vh);
  transform:translateY(14px) scale(.97);transition:transform .26s cubic-bezier(.16,1,.3,1);}

/* Padding, not a margin on the board. A top margin on the first in flow
   child collapses straight through this element, which has no padding or
   border of its own, and moves the whole block including the face that the
   board is supposed to be clearing. */
.gdp-throw-main{min-width:0;position:relative;padding-top:10%;}

/* Over the board, not under it.

   It sat underneath when this corner held the opponent's name, so a long
   one could tuck away behind the circle. The name has since been replaced
   by their remaining score, which is short, and the camera now zooms: at
   three times magnification the board fills its box and would swallow both
   the face and the score exactly when they are being watched. */
.gdp-throw-player{
  position:absolute;top:0;left:0;right:0;z-index:3;
  display:flex;flex-direction:row;align-items:flex-start;
  justify-content:space-between;gap:10px;
  pointer-events:none;
}
/* The board drops clear of the face rather than tucking under it.
   Geometry: with the avatar at 21% of the width in the corner, a drop of
   6.3% is where the two circles stop touching. 7.5% leaves a little air.
   A percentage, because it is measured against the width the avatar is
   also sized from, so the two scale together. */
.gdp-throw-boardwrap{position:relative;z-index:2;}

/* 21% of the board width is the limit: the numbers sit at 94% of the
   radius, and anything larger starts covering the 20 and the 12. */
.gdp-throw-avatar{
  width:21%;max-width:132px;height:auto;aspect-ratio:1;
  border-radius:50%;
  background:#1d1d1d center/cover no-repeat;
  border:3px solid var(--gdp-accent);
  box-shadow:0 0 0 1px rgba(0,0,0,.7), 0 0 18px rgba(255,164,0,.22);
}
.gdp-throw-id{
  text-align:right;padding-top:2px;
  max-width:52%;min-width:0;
  /* Enough to lift the number off whatever the zoomed board puts behind
     it, without drawing a panel round it. */
  text-shadow:0 2px 18px rgba(0,0,0,.95);
}
.gdp-throw.is-open .gdp-throw-panel{transform:none;}

.gdp-throw-left{display:block;font-family:var(--gdp-font);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gdp-muted);margin-top:3px;white-space:nowrap;
  text-shadow:0 1px 8px rgba(0,0,0,.9);}

.gdp-throw-boardwrap{position:relative;}
.gdp-throw-callouts{position:absolute;inset:0;pointer-events:none;}

/* The label lifts away from the dart and fades, so it reads as a callout
   rather than a tooltip stuck to the board. Every property is stated
   explicitly and the colours are literals rather than inherited, because
   this element lives outside the game container and picks up whatever the
   surrounding theme happens to set. Sized to be read from three metres. */
.gdp-callout{
  position:absolute;
  transform:translate(-50%,-50%) scale(.7);
  background-color:#f2f6fb !important;
  color:#0b0f16 !important;
  font-family:var(--gdp-font);
  font-size:24px;
  font-weight:600;
  line-height:1.15;
  letter-spacing:.01em;
  text-transform:none;
  text-shadow:none;
  padding:8px 18px;
  border:2px solid #0b0f16;
  border-radius:30px;
  white-space:nowrap;
  opacity:0;
  margin:0;
  box-shadow:0 10px 30px rgba(0,0,0,.65);
  transition:transform .34s cubic-bezier(.16,1,.3,1),opacity .22s ease;
}
/* Coloured by the ring that was hit, so the kind of dart registers before
   the words are read. Bullseye is a double and comes out orange, outer bull
   is a single and comes out white, with no special casing. */
.gdp-callout.is-single{background-color:#f2f6fb !important;color:#0b0f16 !important;}
.gdp-callout.is-double{background-color:#ff9000 !important;color:#241000 !important;}
.gdp-callout.is-treble{background-color:#2fd07a !important;color:#04230f !important;}
.gdp-callout.is-miss{background-color:#7a8798 !important;color:#0b0f16 !important;}

.gdp-callout.is-on{opacity:1;transform:translate(-50%,-158%) scale(1);}
.gdp-callout.is-off{opacity:0;transform:translate(-50%,-240%) scale(.94);
  transition:transform .42s ease-in,opacity .42s ease-in;}

@media(max-width:600px){ .gdp-callout{font-size:19px;padding:6px 14px;} }

@media(max-width:640px){
  .gdp-throw-panel{max-width:440px;}
  .gdp-throw-avatar{border-width:2px;}
}

/* The three darts and the total. Sized up: this is the row a player reads
   from across the room once the board has been put away, and it had been
   sitting at caption size. */
.gdp-throw-foot{display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-top:14px;padding-top:13px;border-top:1px solid var(--gdp-line);}
.gdp-throw-darts{display:flex;gap:8px;}
.gdp-throw-chip{font-family:var(--gdp-font);
  font-size:clamp(22px,4.6vw,32px);line-height:1;
  padding:10px 0;min-width:clamp(56px,11vw,78px);text-align:center;
  border-radius:10px;background:var(--gdp-panel2);
  border:1px solid var(--gdp-line);opacity:0;transform:translateY(6px);
  transition:opacity .2s ease,transform .24s cubic-bezier(.16,1,.3,1);}
.gdp-throw-chip.is-on{opacity:1;transform:none;}
.gdp-throw-chip.is-single{border-color:#f2f6fb;color:#f2f6fb;}
.gdp-throw-chip.is-double{border-color:#ff9000;color:#ff9000;}
.gdp-throw-chip.is-treble{border-color:#2fd07a;color:#2fd07a;}
.gdp-throw-chip.is-miss{border-color:#7a8798;color:#7a8798;}
.gdp-throw-total{text-align:right;}
.gdp-throw-total b{font-family:var(--gdp-font);display:block;
  font-size:clamp(46px,10vw,74px);font-weight:600;line-height:.95;
  font-variant-numeric:tabular-nums;}
.gdp-throw-label{display:block;font-family:var(--gdp-font);
  font-size:clamp(11px,1.8vw,14px);letter-spacing:.16em;text-transform:uppercase;
  color:var(--gdp-muted);}
/* Once the visit is closed the total stops being a running tally. */
.gdp-throw-total.is-final b{transition:color .2s ease;}
.gdp-throw-total.is-bust b{color:var(--gdp-bust);font-size:clamp(34px,7vw,54px);}
.gdp-throw-total.is-checkout b{color:var(--gdp-win);}
.gdp-throw-total.is-final .gdp-throw-label{color:var(--gdp-ink);}

/* =====================================================================
   The closed door, and the feedback ribbon
   ===================================================================== */

.gdp-closed{max-width:560px;margin:60px auto;text-align:center;
  background:rgba(12,12,12,.82);border:1px solid var(--gdp-frame);
  border-radius:var(--gdp-radius);padding:34px 30px 36px;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);}
.gdp-closed h1{font-family:var(--gdp-font);font-size:clamp(30px,6vw,46px);
  margin:0 0 14px;letter-spacing:.02em;}
.gdp-closed p{color:var(--gdp-muted);font-size:15px;line-height:1.6;margin:0 0 14px;}
.gdp-closed .gdp-btn{display:inline-block;text-decoration:none;margin-top:6px;}

/* Along the top border, the way the Performance Center carries it, and
   set well left of the Scolia badge so the two never meet.

   text-transform is none rather than uppercase: the label is meant to read
   "Feedback", and uppercasing it in the stylesheet would show FEEDBACK
   whatever the markup says. */
.gdp-ribbon{
  position:absolute;
  top:0;
  right:210px;
  z-index:1205;
  cursor:pointer;
  display:flex;
  align-items:center;
  gap:7px;
  height:24px;
  padding:0 12px;
  font-family:var(--gdp-font);
  font-size:11px;
  letter-spacing:.12em;
  text-transform:none;
  white-space:nowrap;
  color:#fff;
  background:#d8455c;
  border:0;
  border-radius:0 0 7px 7px;
  box-shadow:0 4px 14px rgba(0,0,0,.45);
}
.gdp-ribbon i{font-size:10px;}
.gdp-ribbon:hover{background:#e6566c;}

/* The panel is lifted out of the flow so nothing absolutely positioned
   inside the modal can paint over it. */
.gdp-modal-panel{position:relative;}
.gdp-modal-panel h3{font-family:var(--gdp-font);font-size:21px;margin:0 0 8px;}
.gdp-modal-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:14px;}
/* Unscoped: the dialog sits outside the game wrapper, because it covers
   the window rather than the frame. */
.js-feedback-text{
  width:100%;background:var(--gdp-panel2);color:var(--gdp-ink);
  border:1px solid var(--gdp-frame);border-radius:10px;
  padding:11px 13px;font-family:var(--gdp-font-note);font-size:14.5px;
  resize:vertical;margin-top:10px;
}
.js-feedback-text:focus{outline:none;border-color:var(--gdp-accent);}

@media(max-width:700px){
  /* The badge is narrower here and sits closer in, so the ribbon can be
     closer too. Below this the two would meet, so it moves to the left. */
  .gdp-ribbon{right:150px;padding:0 11px;}
}
/* It stays on the right at every width. Measured against the badge it has
   to clear: at 320px the ribbon ends at 170 and the badge starts at 196,
   so there is room without sending it to the other side of the frame. */
@media(max-width:520px){
  .gdp-ribbon{right:132px;padding:0 9px;gap:5px;letter-spacing:.06em;}
}

/* =====================================================================
   Your stats

   The tab is the one every other game on the platform has, in the same
   place, so it is found without being looked for.
   ===================================================================== */

/* Turned on its top right corner rather than its centre. Rotating about
   the centre and nudging it back needs a translate along the rotated axes,
   which is why the old one would not sit flush.

   CSS rotate(-90deg) sends a point (x, y) to (y, -x), so the button grows
   right by its own height and down by its width from that corner. Setting
   it in from the border by exactly that height lands its edge on the
   border, and it is the button's TOP corners that end up facing inward,
   which is why the radius is on those two. */
.gdp-statstab{
  position:absolute;
  top:170px;
  right:var(--gdp-tab-h);
  height:var(--gdp-tab-h);
  transform:rotate(-90deg);
  transform-origin:100% 0;
  z-index:1210;cursor:pointer;
  display:flex;align-items:center;
  font-family:var(--gdp-font);font-size:13px;letter-spacing:.16em;
  text-transform:uppercase;white-space:nowrap;
  padding:0 20px;
  color:var(--gdp-accent-ink);background:var(--gdp-accent);
  border:0;
  /* Square where it meets the border, rounded where it faces the game. */
  border-radius:9px 9px 0 0;
  box-shadow:-3px 0 14px rgba(0,0,0,.45);
}
.gdp-statstab:hover{filter:brightness(1.08);}

/* Bounded by the game, not the window. The stats belong to this game, so
   covering the header, the menu and the rest of the site to show them is
   more than the moment deserves. */
.gdp-stats{position:absolute;inset:0;z-index:1400;display:none;
  border-radius:var(--gdp-radius);overflow:hidden;}
.gdp-stats.is-open{display:block;}
.gdp-stats-scrim{position:absolute;inset:0;background:rgba(0,0,0,.72);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);}

/* The full width of the game. It began as a drawer down the right, which
   left the heat map squeezed into a column while two thirds of the frame
   sat empty behind it. */
.gdp-stats-panel{
  position:absolute;inset:0;
  background:var(--gdp-bg);
  display:flex;flex-direction:column;
  transform:translateY(-14px);opacity:0;
  transition:transform .28s cubic-bezier(.16,1,.3,1), opacity .22s ease;
}
.gdp-stats.is-open .gdp-stats-panel{transform:none;opacity:1;}

.gdp-stats-head{display:flex;align-items:center;justify-content:space-between;
  padding:18px 20px 14px;border-bottom:1px solid var(--gdp-line);}
.gdp-stats-head h2{font-family:var(--gdp-font);font-size:22px;margin:0;
  letter-spacing:.04em;}
.gdp-stats-body{flex:1;overflow-y:auto;padding:18px 22px 28px;
  /* The platform scrollbar is a grey slab against this. Firefox takes the
     two properties, everything else takes the pseudo elements. */
  scrollbar-width:thin;
  scrollbar-color:rgba(255,164,0,.45) transparent;
}
.gdp-stats-body::-webkit-scrollbar{width:8px;}
.gdp-stats-body::-webkit-scrollbar-track{background:transparent;}
.gdp-stats-body::-webkit-scrollbar-thumb{
  background:rgba(255,255,255,.16);border-radius:8px;
  border:2px solid transparent;background-clip:content-box;
}
.gdp-stats-body::-webkit-scrollbar-thumb:hover{background-color:rgba(255,164,0,.55);
  background-clip:content-box;}

/* Two columns once there is room for them: what the darts did on the
   left, which match produced it on the right. */
.gdp-stats-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,440px);
  gap:30px;align-items:start;}
@media(max-width:900px){ .gdp-stats-grid{grid-template-columns:1fr;gap:18px;} }

/* Which match is being shown. A heading, not a panel. */
.gdp-scope-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
  font-family:var(--gdp-font);font-size:clamp(19px,2.6vw,25px);font-weight:400;
  margin:0 0 16px;letter-spacing:.02em;}
.gdp-scope-head span{font-size:13px;color:var(--gdp-muted);}
.gdp-scope-head .gdp-chip{margin-left:auto;}

/* The lightbulb. The advice is worth a look once and then rarely again,
   so it sits behind a button instead of taking a block of the panel from
   everybody who has already read it. */
.gdp-bulb{width:30px;height:30px;padding:0;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--gdp-panel2);color:var(--gdp-muted);
  border:1px solid var(--gdp-frame);cursor:pointer;margin-left:4px;}
.gdp-bulb:hover{color:var(--gdp-accent);border-color:var(--gdp-accent);}
.gdp-stats-loading{color:var(--gdp-muted);font-family:var(--gdp-font);
  text-align:center;padding:40px 0;}

/* ---------- the headline numbers ---------- */
/* Two across rather than three, so the block stands as tall as the board
   beside it. Three across left a third of the panel empty. */
.gdp-figures{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;
  margin-bottom:20px;}
.gdp-figures.is-thirds{grid-template-columns:repeat(3,1fr);}
.gdp-figure{background:var(--gdp-panel);border:1px solid var(--gdp-line);
  border-radius:11px;padding:13px 12px;text-align:center;}
.gdp-figure b{display:block;font-family:var(--gdp-font);font-weight:600;
  font-size:clamp(22px,5vw,30px);line-height:1;font-variant-numeric:tabular-nums;}
.gdp-figure span{display:block;font-family:var(--gdp-font);font-size:10px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--gdp-muted);
  margin-top:6px;}

.gdp-stats-h3{font-family:var(--gdp-font);font-size:12px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--gdp-accent);margin:0 0 10px;}
.gdp-stats-h3.is-centred{text-align:center;}

/* ---------- the heat map ---------- */
.gdp-heat{position:relative;max-width:420px;margin:0 auto 6px;}
.gdp-heat canvas{position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;}
.gdp-heat-note{font-family:var(--gdp-font);font-size:12px;color:var(--gdp-muted);
  text-align:center;margin-bottom:16px;}
.gdp-heat-modes{display:flex;gap:6px;justify-content:center;margin-bottom:12px;}

/* Shown instead of the map when nothing was ever tracked. */
.gdp-teaser{background:var(--gdp-panel);border:1px solid var(--gdp-accent);
  border-radius:var(--gdp-radius);padding:16px 18px;margin-bottom:22px;}
.gdp-teaser h4{font-family:var(--gdp-font);font-size:16px;margin:0 0 6px;
  color:var(--gdp-accent);}
.gdp-teaser p{font-size:13.5px;color:var(--gdp-muted);margin:0 0 12px;line-height:1.5;}
.gdp-teaser a{display:inline-block;font-family:var(--gdp-font);font-size:13px;
  letter-spacing:.08em;text-transform:uppercase;text-decoration:none;
  color:var(--gdp-accent-ink);background:var(--gdp-accent);
  padding:9px 18px;border-radius:9px;}

/* ---------- where to aim ---------- */
.gdp-advice{background:var(--gdp-panel);border:1px solid var(--gdp-line);
  border-left:3px solid var(--gdp-accent);
  border-radius:11px;padding:14px 16px;margin-bottom:14px;}
.gdp-advice p{margin:0 0 8px;font-size:13.5px;line-height:1.55;color:var(--gdp-muted);}
.gdp-advice p:last-child{margin-bottom:0;}
.gdp-advice b{color:var(--gdp-ink);font-weight:400;}

.gdp-perf-link{text-align:center;margin-top:14px;}
.gdp-perf-link a{font-family:var(--gdp-font);font-size:13px;
  color:var(--gdp-muted);text-decoration:none;
  border-bottom:1px solid var(--gdp-line);padding-bottom:2px;}
.gdp-perf-link a:hover{color:var(--gdp-accent);border-color:var(--gdp-accent);}

/* ---------- leg by leg ----------
   Only present when one match is in scope. Narrower than the match list
   because it carries fewer numbers and sits above it. */
.gdp-leg{
  display:grid;
  grid-template-columns:46px minmax(0,1fr) minmax(0,1fr) 62px 62px 50px;
  align-items:center;gap:10px;
  padding:8px 12px;border-radius:9px;
  border:1px solid var(--gdp-line);margin-bottom:5px;
  font-family:var(--gdp-font);font-size:13.5px;cursor:pointer;
}
.gdp-leg:hover{border-color:var(--gdp-accent);}
.gdp-leg.is-on{border-color:var(--gdp-accent);background:#1a1305;}
.gdp-leg.is-head{border-color:transparent;background:none;cursor:default;
  font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gdp-muted);margin-bottom:2px;}
.gdp-leg.is-head:hover{border-color:transparent;}
.gdp-leg-num{text-align:right;font-variant-numeric:tabular-nums;
  color:var(--gdp-muted);}
.gdp-leg-num.is-mine{color:var(--gdp-ink);}
.gdp-leg.is-win{border-left:3px solid var(--gdp-win);}
.gdp-leg.is-loss{border-left:3px solid var(--gdp-line);}
.gdp-leg.is-head.is-win,.gdp-leg.is-head.is-loss{border-left-color:transparent;}
/* The green dot moved off the average and onto the leg number. Sitting
   beside "You" it read as a mark on the player rather than a note that
   the darts were tracked, and it was on every leg regardless. */
.gdp-leg-no{display:flex;align-items:center;gap:7px;}
.gdp-leg-mark{
  font-size:10px;font-weight:400;letter-spacing:.06em;
  width:17px;height:17px;border-radius:5px;
  display:inline-flex;align-items:center;justify-content:center;
}
.gdp-leg.is-win .gdp-leg-mark{background:rgba(61,220,132,.16);color:var(--gdp-win);}
.gdp-leg.is-loss .gdp-leg-mark{background:rgba(255,255,255,.06);color:var(--gdp-muted);}
.gdp-leg-num.is-won{color:var(--gdp-win);}
.gdp-leg.is-tracked .gdp-leg-no::before{
  content:"";width:5px;height:5px;border-radius:50%;
  background:var(--gdp-win);opacity:.55;flex:0 0 5px;
}

/* A leg opened out: every visit, both players, side by side. */
.gdp-leg-open{margin:-2px 0 8px;padding:10px 12px 11px;
  border:1px solid var(--gdp-line);border-top:0;
  border-radius:0 0 9px 9px;background:rgba(255,255,255,.02);}
.gdp-visits{display:grid;grid-template-columns:1fr 1fr;gap:5px 14px;}
.gdp-visit-head{font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gdp-muted);padding-bottom:2px;}
.gdp-visit{display:flex;align-items:baseline;justify-content:space-between;
  gap:10px;font-variant-numeric:tabular-nums;
  padding:3px 8px;border-radius:6px;background:rgba(255,255,255,.03);}
.gdp-visit b{font-size:14px;font-weight:400;}
.gdp-visit i{font-size:12px;font-style:normal;color:var(--gdp-muted);}
.gdp-visit.is-bust b{color:var(--gdp-bust);}
.gdp-visit.is-out b{color:var(--gdp-win);}
.gdp-visit.is-blank{background:none;}

@media(max-width:760px){
  .gdp-leg{grid-template-columns:40px 1fr 1fr 52px;}
  .gdp-leg > :nth-child(5),.gdp-leg > :nth-child(6){display:none;}
}

/* ---------- recent matches ----------
   A table in all but name. Grid rather than a real one because each row
   has to fold into a card on a phone, and a table cannot be persuaded to
   do that without fighting it. */
.gdp-stats-list{margin-top:26px;}

.gdp-session{
  display:grid;
  grid-template-columns:9px 66px minmax(0,1fr) 52px 58px 58px 66px 62px 46px;
  align-items:center;gap:10px;
  padding:10px 12px;border-radius:10px;
  border:1px solid var(--gdp-line);margin-bottom:6px;
  font-family:var(--gdp-font);cursor:pointer;
}
.gdp-session:hover{border-color:var(--gdp-accent);}
.gdp-session.is-on{border-color:var(--gdp-accent);background:#1a1305;}

/* The column labels, which are a row like any other so the widths cannot
   drift apart from the rows they head. */
.gdp-session.is-head{
  border-color:transparent;background:none;cursor:default;margin-bottom:2px;
  font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gdp-muted);
}
.gdp-session.is-head:hover{border-color:transparent;}

.gdp-session-when{font-size:11.5px;color:var(--gdp-muted);}
.gdp-session-who{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.gdp-session-legs{font-size:14px;font-variant-numeric:tabular-nums;text-align:center;}
.gdp-session.is-win .gdp-session-legs{color:var(--gdp-win);}
.gdp-session.is-loss .gdp-session-legs{color:var(--gdp-muted);}
.gdp-session-num{font-size:13.5px;font-variant-numeric:tabular-nums;
  text-align:right;color:var(--gdp-muted);}
.gdp-session-num.is-avg{font-size:16px;color:var(--gdp-ink);}
.gdp-session.is-head .gdp-session-num{font-size:10px;}
.gdp-session-dot{width:7px;height:7px;border-radius:50%;background:var(--gdp-line);}
.gdp-session.is-tracked .gdp-session-dot{background:var(--gdp-win);}

/* On a phone the row folds into a card: who and what on the first line,
   the numbers underneath with their labels attached, because a column
   heading eight rows up helps nobody. */
@media(max-width:760px){
  .gdp-session.is-head{display:none;}
  .gdp-session{
    grid-template-columns:9px 66px minmax(0,1fr) 52px;
    gap:8px 10px;row-gap:9px;padding:11px 13px;
  }
  .gdp-session-num{
    grid-column:span 2;text-align:left;font-size:12.5px;
    display:flex;align-items:baseline;gap:6px;
  }
  .gdp-session-num::before{
    content:attr(data-label);
    font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;
    color:var(--gdp-muted);opacity:.75;
  }
  .gdp-session-num.is-avg{font-size:15px;}
}

@media(max-width:700px){
  .gdp-statstab{top:120px;font-size:12px;padding:0 15px;}
  .gdp-stats-panel{width:100%;}
  .gdp-figures{grid-template-columns:repeat(2,1fr);}
}

/* =====================================================================
   Announcements
   ===================================================================== */

/* "Remove your darts", on the brand angle.

   The 18 degrees is the same line that runs across the setup background,
   so the banner reads as part of the identity rather than a notification.
   It sits outside the frame on both sides and sweeps across, which is why
   the width is over 140%: rotating a full width bar leaves the corners
   short, and the overhang covers them. */
/* The banner runs past both edges of the frame, so it is clipped to it.
   The clipping cannot go on the frame itself: the Scolia badge straddles
   the top border on purpose, and its device list hangs outside, so hiding
   overflow there would cut both of them off. A layer of its own, sized to
   the inside of the border and sharing its radius, clips the banner and
   nothing else. */
.gdp-remove-clip{
  position:absolute;
  inset:0;
  overflow:hidden;
  border-radius:var(--gdp-radius);
  pointer-events:none;
  z-index:1180;
}

.gdp-remove{
  position:absolute;
  left:-22%;
  width:144%;
  /* High enough that the text, which sits at the centre of the band, lands
     above the tracked dart boxes. Those are drawn over the banner so the
     scores stay readable, which means anything the band puts underneath
     them cannot be read at all. The banner carries its own background, so
     crossing the big score costs nothing. */
  top:30%;
  pointer-events:none;
  text-align:center;
  padding:16px 0 15px;
  transform:rotate(-18deg) translateX(-120%);
  opacity:0;
  /* Translucent enough for the score to show through as it passes. The
     comment above about the banner carrying its own background no longer
     holds: it now borrows what is behind it, so the text needs its own
     shadow to stay readable. */
  background:linear-gradient(90deg,
    rgba(18,13,2,0) 0%, rgba(18,13,2,.8) 14%,
    rgba(18,13,2,.8) 86%, rgba(18,13,2,0) 100%);
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
  border-top:2px solid var(--gdp-accent);
  border-bottom:1px solid rgba(255,164,0,.4);
}

/* One sweep rather than an in and an out. It comes in slowly from the left,
   picks up speed as it reaches the middle, settles just long enough to be
   read, then accelerates away to the right. Timing is set per keyframe,
   because a single easing curve cannot be slow at one end, still in the
   middle and quick at the other. */
@keyframes gdpSweep{
  0%   {transform:rotate(-18deg) translateX(-120%);opacity:0;
        animation-timing-function:cubic-bezier(.4,.02,.62,.3);}
  14%  {opacity:1;}
  52%  {transform:rotate(-18deg) translateX(-5%);
        animation-timing-function:cubic-bezier(.2,.7,.35,1);}
  63%  {transform:rotate(-18deg) translateX(0);
        animation-timing-function:linear;}
  76%  {transform:rotate(-18deg) translateX(3%);opacity:1;
        animation-timing-function:cubic-bezier(.5,0,.78,.1);}
  100% {transform:rotate(-18deg) translateX(122%);opacity:0;}
}
.gdp-remove.is-on{animation:gdpSweep 3.2s both;}
@media(prefers-reduced-motion:reduce){
  .gdp-remove.is-on{animation:none;transform:rotate(-18deg);opacity:1;}
}
.gdp-remove-text{
  text-shadow:0 2px 12px rgba(0,0,0,.9), 0 0 3px rgba(0,0,0,.8);
  font-family:var(--gdp-font);font-weight:600;
  font-size:clamp(20px,3.6vw,40px);
  letter-spacing:.24em;text-transform:uppercase;color:#fff;
  text-shadow:0 2px 16px rgba(0,0,0,.95);
}

/* A treble in the big beds, a bull, or the dart that wins the leg.
   Keeps breathing until the boxes are cleared for the next visit or the
   player taps the box to correct it, so the hit is still marked when they
   look back at the row rather than having flashed and gone. Slower and
   softer than a one shot pulse, because this one has to be liveable with
   for a whole visit. */
@keyframes gdpBoxHit{
  0%,100% {box-shadow:0 0 0 0 rgba(61,220,132,0),  0 0 8px 0 rgba(61,220,132,.25);}
  50%     {box-shadow:0 0 0 3px rgba(61,220,132,.12), 0 0 26px 5px rgba(61,220,132,.7);}
}
.gdp .dart-detail.is-hit{
  animation:gdpBoxHit 1.4s ease-in-out infinite;
  border-color:var(--gdp-win) !important;
}
@media(prefers-reduced-motion:reduce){
  .gdp .dart-detail.is-hit{animation:none;box-shadow:0 0 20px 3px rgba(61,220,132,.55);}
}

/* Sits on the top edge of the frame, clear of the dart boxes underneath
   the score, and narrow enough not to reach the Scolia badge. */
.gdp-flash{position:absolute;top:9px;left:50%;
  transform:translate(-50%,-16px);
  background:var(--gdp-win);color:#04230f;
  font-family:var(--gdp-font);font-size:clamp(15px,2.2vw,21px);font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;
  padding:9px 26px;border-radius:22px;
  box-shadow:0 8px 26px rgba(0,0,0,.6);
  opacity:0;pointer-events:none;z-index:1150;
  transition:opacity .18s ease,transform .32s cubic-bezier(.16,1,.3,1);}
.gdp-flash.is-open{opacity:1;transform:translate(-50%,0);}
.gdp-flash.is-match{background:var(--gdp-accent);color:var(--gdp-accent-ink);}
@media(max-width:600px){ .gdp-flash{padding:7px 16px;} }
.gdp-announce{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
  pointer-events:none;opacity:0;transition:opacity .18s;z-index:900;}
.gdp-announce.is-open{opacity:1;}
.gdp-announce-inner{background:rgba(13,17,23,.94);border:2px solid var(--gdp-accent);
  border-radius:20px;padding:24px 44px;text-align:center;min-width:250px;}
.gdp-announce.is-bust .gdp-announce-inner{border-color:var(--gdp-bust);}
.gdp-announce.is-checkout .gdp-announce-inner{border-color:var(--gdp-win);}
.gdp-announce-who{font-family:var(--gdp-font);font-size:13px;letter-spacing:.2em;text-transform:uppercase;color:var(--gdp-muted);}
.gdp-announce-score{font-family:var(--gdp-font);font-size:82px;line-height:1;font-weight:600;font-variant-numeric:tabular-nums;}
.gdp-announce.is-bust .gdp-announce-score{color:var(--gdp-bust);font-size:52px;}
.gdp-announce.is-checkout .gdp-announce-score{color:var(--gdp-win);}
.gdp-announce-left{font-family:var(--gdp-font);font-size:15px;color:var(--gdp-muted);letter-spacing:.1em;}

.gdp-toast{font-family:var(--gdp-font);position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(14px);
  background:var(--gdp-panel);border:1px solid var(--gdp-line);border-radius:10px;padding:10px 17px;
  font-size:14px;opacity:0;transition:.2s;z-index:950;pointer-events:none;max-width:90vw;}
.gdp-toast.is-open{opacity:1;transform:translateX(-50%) translateY(0);}
.gdp-toast.is-bust{border-color:var(--gdp-bust);}

/* =====================================================================
   Result
   ===================================================================== */
.gdp-result{width:100%;max-width:600px;margin:18px auto;border-collapse:collapse;}
.gdp-result th,.gdp-result td{font-family:var(--gdp-font);padding:8px 12px;font-size:16px;font-variant-numeric:tabular-nums;}
.gdp-result thead th{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--gdp-accent);}
.gdp-result tbody th{font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gdp-muted);font-weight:400;width:44%;}
.gdp-result td{text-align:center;}
.gdp-result tbody tr{border-top:1px solid var(--gdp-line);}

@media(max-width:600px){
  .gdp-wrap{padding:16px 13px 24px;min-height:560px;}
  .gdp-tally{gap:18px;}
  .gdp-finish{font-size:15px;padding:7px 12px;}
  .gdp-display-value{font-size:36px;}
  .gdp-checkout-bar{min-height:46px;margin-bottom:6px;}
  .gdp-bar-rules{width:100%;}
  .gdp-throw-panel{padding:12px;}
}

@media(prefers-reduced-motion:reduce){
  .gdp *,.gdp-throw,.gdp-throw-panel,.gdp-callout,.gdp-throw-chip{
    transition:none !important;animation:none !important;}
}
