/* 589comps.css - the dark look for the page Quick Start
   generated. A starting point, not a house style: none of it is
   needed for the competition to work, and every rule here is yours
   to change.

   GENERATED. Generating the page again writes this file again, so
   put your own rules in a stylesheet of your own, linked after this
   one - they will win on equal specificity and survive the next
   generate.

   IT DOES NOT TOUCH THE WIDGETS. They carry their own colours, set
   in Quick Start under "Colours"; every rule below is anchored to
   the markup Quick Start writes. Nothing inside either widget is
   yours to select. */
:root {
  --page-bg: #14171c;
  --page-panel: #1c2027;
  --page-ink: #e8ebef;
  --page-soft: #a2acba;
  --page-line: #2a3038;
  --page-accent: #5aa2ff;
  --page-accent-ink: #0d1117;
  --page-error-bg: #3a1f1d;
  --page-error-ink: #ffb4ab;
  --page-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .35);
  --page-bg-2: #1a1e25;
  --page-accent-2: #7cc0ff;
  --hero-from: #5aa2ff;
  --hero-ink: #0d1117;
  --hero-tint: rgba(0, 0, 0, .14);
  --page-live: #35c46a;
  --page-idle: #e2574c;
  --page-radius: 10px;
  --page-width: 960px;
  --page-rail: 300px;
  --page-gap: 20px;
}
html { color-scheme: dark; }
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--page-bg);
  color: var(--page-ink);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-text-size-adjust: 100%;
}

/* The bar across the top, and everything under it in one column. */
body > header {
  background: var(--page-panel);
  border-bottom: 1px solid var(--page-line);
}
body > header nav {
  width: min(var(--page-width), 100% - 2rem);
  margin: 0 auto;
  display: flex;
  align-items: center;
  min-height: 56px;
}
body > header > nav > ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin: 0;
  padding: 0;
  width: 100%;
}
body > header > nav > ul > li[data-589comps-account] { margin-left: auto; }
body > header > nav > ul > li > a, body > header > nav > .site-name {
  color: var(--page-ink);
  text-decoration: none;
  font-weight: 600;
  padding: 6px 2px;
  border-bottom: 2px solid transparent;
}
body > header > nav > ul > li > a:hover, body > header > nav > ul > li > a:focus-visible { border-bottom-color: var(--page-accent); }

body > *:not(header):not(script) {
  width: min(var(--page-width), 100% - 2rem);
  margin: 1.5rem auto;
}

/* The sections Quick Start writes. The widgets inside them bring
   their own look. */
body > section {
  background: var(--page-panel);
  border: 1px solid var(--page-line);
  border-radius: var(--page-radius);
  box-shadow: var(--page-shadow);
  padding: 1.25rem 1.25rem 1.5rem;
}
h1, h2, h3 { line-height: 1.25; margin: 0 0 .6rem; }
h1 { font-size: 1.75rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1rem; color: var(--page-soft); text-transform: uppercase; letter-spacing: .04em; }

/* Sign in and sign up, side by side where there is room. */
#comps-signin form {
  display: grid;
  gap: .75rem;
  align-content: start;
}
[hidden] { display: none !important; }
#comps-signin {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
}
@media (min-width: 720px) {
  #comps-signin { grid-template-columns: 1fr 1fr; }
  #comps-signin > h2, #comps-signin > p { grid-column: 1 / -1; }
}
#comps-signin label { display: grid; gap: .3rem; font-size: .9rem; color: var(--page-soft); }
/* Buttons size to their words, rather than stretching across the
   column they happen to sit in. */
#comps-signin button { justify-self: start; }
#comps-signin input {
  font: inherit;
  padding: .6rem .7rem;
  color: var(--page-ink);
  background: var(--page-bg);
  border: 1px solid var(--page-line);
  border-radius: 8px;
}
#comps-signin input:focus-visible { outline: 2px solid var(--page-accent); outline-offset: 1px; }
#comps-signin-error {
  background: var(--page-error-bg);
  color: var(--page-error-ink);
  border-radius: 8px;
  padding: .6rem .8rem;
  margin: 0;
}

button, #comps-signin button, #comps-signout {
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  padding: .6rem 1.1rem;
  border-radius: 8px;
  border: 1px solid transparent;
  background: var(--page-accent);
  color: var(--page-accent-ink);
}
#comps-signout {
  background: transparent;
  color: var(--page-soft);
  border-color: var(--page-line);
  padding: .35rem .85rem;
  font-size: .9rem;
  /* In the bar beside My account since 1.471.0; still a body child on
     a page with no navigation, where the column rule would stretch it. */
  width: auto;
  display: block;
}
#comps-signout:hover { color: var(--page-ink); border-color: var(--page-accent); filter: none; }
button:hover { filter: brightness(1.08); }
button:focus-visible { outline: 2px solid var(--page-accent); outline-offset: 2px; }

/* ---- A COMPLETE PAGE (1.467.0) ----
   Asked for on 23 Sep 2026: the light and dark templates as complete
   pages, "nicely styled and presented so a prospective partner can
   get an idea of what their site could look like using one of these
   templates". The markup is the same in all three - only this
   stylesheet differs - so what follows is the part that turns it
   from a column of widgets into something that reads as a site. */

/* The site's name, at the left of the bar. */
.site-name {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: var(--page-ink);
  text-decoration: none;
  margin-right: 1.5rem;
  white-space: nowrap;
}
.site-name:hover { color: var(--page-accent); }

/* The bar itself sits above everything and stays put while you read. */
body > header {
  position: sticky;
  top: 0;
  z-index: 10;
  backdrop-filter: blur(6px);
}
body > header > nav > ul > li > a { color: var(--page-soft); text-decoration: none; }
body > header > nav > ul > li > a:hover { color: var(--page-ink); }
/* Which view you are on (1.471.0): Home or Winners. */
body > header > nav > ul > li > a[aria-current="page"] {
  color: var(--page-ink);
  border-bottom-color: var(--page-accent);
}

/* ---- THE WINNERS TABLE (1.471.0) ----
   Asked for on 25 Sep 2026 with the Winners view: a list of winners
   and a link to the replay for each competition. Nine fields as one
   long line of Label: value each was the shape the request arrived
   with a screenshot of. */
.comps-winners { width: 100%; border-collapse: collapse; font-size: .95rem; }
.comps-winners th {
  text-align: left;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  font-weight: 600;
  color: var(--page-soft);
  white-space: nowrap;
  padding: .45rem .7rem;
  border-bottom: 1px solid var(--page-line);
}
.comps-winners td { padding: .6rem .7rem; border-bottom: 1px solid var(--page-line); }
.comps-winners tbody tr:last-child td { border-bottom: 0; }
.comps-winners tbody tr:hover { background: var(--page-bg); }
/* Nine columns on a phone scroll sideways rather than squashing into
   one letter each. */
[data-comps-group="winners"] { overflow-x: auto; }

/* ---- THE FIELD CARDS (1.475.0) ----
   Asked for on 26 Sep 2026: "can we make the cards/data below look
   presentable to a prospective partner?" Each section was a run of
   "Label: value" lines - this is the same markup as two columns,
   with the label quiet and the value doing the talking. */
.comps-fields { display: grid; grid-template-columns: minmax(0, 1fr) fit-content(60%); margin: 0; }
.comps-fields dt {
  color: var(--page-soft);
  font-size: .92rem;
  padding: .5rem .9rem .5rem 0;
  border-bottom: 1px solid var(--page-line);
  min-width: 0;
}
.comps-fields dd {
  margin: 0;
  font-weight: 600;
  text-align: right;
  padding: .5rem 0;
  border-bottom: 1px solid var(--page-line);
  /* A URL or an id is one long word; let it break rather than push
     the card wider than the page. */
  overflow-wrap: anywhere;
}
.comps-fields dt:last-of-type, .comps-fields dd:last-of-type { border-bottom: 0; }
/* THE REVEALED PICTURE (1.489.0). The cap on its size is set on the
   element itself, because the unstyled template has no stylesheet to
   carry one; what is here is the look, which that template has none
   of by design. */
.comps-fields dd img {
  display: inline-block;
  border-radius: var(--page-radius);
  border: 1px solid var(--page-line);
  vertical-align: middle;
}

/* ---- A RECORD WITH A PICTURE IN IT (1.525.0) --------------------

   Asked for on 28 Sep 2026: "can you make this a nice looking,
   presentable card so it looks visually appealing" - of Last Result,
   where the revealed image sat in the value column of a two-column
   list with an empty label beside it and a tall band of dead space
   under the label.

   The picture leads the card now, above the fields, with its label
   as the caption so nothing the operator chose to show is lost.
   Only a group carrying a picture gets this; everything else is the
   same list it was.

   AND IT IS SMALL (1.527.0), the same 300px as the rail beside the
   competition. It had the card's full width, which on a wide page
   made the revealed image the biggest thing there. The cap is on
   the element - the unstyled template has no stylesheet - and this
   rule only dresses it. */
/* THE PICTURE BESIDE THE FIELDS, NOT ABOVE THEM (1.527.0). Stacked,
   a 226px picture and seven rows made the shortest possible card
   623px tall - which is not what "small and doesn't take up much
   space" looks like. Side by side it is the height of whichever is
   taller, and it reads as a result rather than a list under a
   photograph. auto, not 300px: the column is exactly as wide as the
   picture turns out to be, so a portrait one does not leave a strip
   of empty rail beside it. */
.comps-record { display: grid; grid-template-columns: fit-content(300px) minmax(0, 1fr); gap: 1rem 1.25rem; align-items: start; }
.comps-shot { margin: 0; display: grid; gap: .45rem; justify-items: center; }
.comps-shot img {
  display: block;
  /* NO width HERE. The element carries max-width/max-height and
     width: auto, which keeps the picture's own proportions with or
     without this stylesheet; a width declared here would be
     overridden by that inline auto anyway and only mislead. */
  border-radius: var(--page-radius);
  border: 1px solid var(--page-line);
  background: var(--page-bg-2);
}
.comps-shot figcaption {
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--page-soft);
}
/* An identifier is something you copy, not something you read: quiet,
   monospaced, and out of the way of the values that carry meaning. */
.comps-fields dd.comps-ref {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .78rem;
  font-weight: 500;
  color: var(--page-soft);
  letter-spacing: 0;
}
/* One column where two will not fit: the label above its value,
   which is what a <dl> does unstyled anyway. The record stacks at
   the same width, for the same reason - a 300px picture and a
   label/value list will not share a phone. */
@media (max-width: 560px) {
  .comps-record { grid-template-columns: minmax(0, 1fr); }
  .comps-fields { grid-template-columns: 1fr; }
  .comps-fields dt { border-bottom: 0; padding-bottom: 0; }
  .comps-fields dd { text-align: left; padding-top: .1rem; }
}
.comps-empty { margin: 0; color: var(--page-soft); }

/* THE BUY CREDIT TAB (1.476.0). It is drawn INSIDE the account
   widget, so it takes the widget's own colours where the widget sets
   them (--c589n-*, from its Colours setting) and the page's where it
   does not - which is Colours: None, where the partner styles the
   widget themselves. Either way the tab matches what it sits in
   rather than fighting it. */
.comps-topup { display: grid; gap: .55rem; }
.comps-topup p { margin: 0; }
.comps-topup-balance { font-weight: 600; }
.comps-topup-rate,
.comps-topup-limits,
.comps-topup-note {
  color: var(--c589n-muted, var(--page-soft));
  font-size: .88rem;
}
.comps-topup-field { display: grid; gap: .25rem; font-size: .92rem; }
.comps-topup-field input {
  font: inherit;
  /* A money box, not a paragraph: wide enough for an amount and no
     wider, whatever the section it is drawn in is. */
  max-width: 12rem;
  padding: .5rem .6rem;
  border-radius: 8px;
  border: 1px solid var(--c589n-line, var(--page-line));
  background: var(--c589n-field-bg, var(--page-bg));
  color: inherit;
}
.comps-topup button {
  font: inherit;
  justify-self: start;
  padding: .5rem 1rem;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  background: var(--c589n-accent, var(--page-accent));
  color: var(--c589n-bg, var(--page-accent-ink));
}
/* A DISABLED BUTTON HAS TO LOOK DISABLED: it starts that way, and
   stays that way until the amount passes the operator's limits. */
.comps-topup button:disabled { opacity: .5; cursor: not-allowed; }
.comps-topup-error { color: var(--c589n-out, var(--page-error-ink)); font-size: .88rem; }
.comps-topup-ok { color: var(--c589n-in, var(--page-ink)); font-size: .92rem; font-weight: 600; }

/* Each widget and each field section reads as a card on the page. */
body > section, body > div[id^="comps-"] {
  background: var(--page-panel);
  border: 1px solid var(--page-line);
  border-radius: var(--page-radius);
  box-shadow: var(--page-shadow);
  padding: 1.1rem 1.25rem;
}
body > section:empty, body > div[id^="comps-"]:empty { display: none; }
body > section > h2 {
  margin: 0 0 .6rem;
  font-size: 1rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--page-soft);
}

/* And the page ends rather than stopping. */
body > footer:last-of-type {
  border-top: 1px solid var(--page-line);
  /* auto rather than a gap: the footer takes whatever height is left
     over, so it ends the page on a short view - one table, say - and
     follows the content on a long one, where the section above it
     brings its own margin. */
  margin-top: auto;
  padding: 1.5rem 0 2.5rem;
  color: var(--page-soft);
  text-align: center;
}
body > footer p { margin: .2rem 0; }

/* ------------------------------------------------------------------
   THE EXAMPLE SITE (1.511.0).

   Asked for on 27 Sep 2026: the light and dark templates as complete
   example websites, so a partner can see what the competitions would
   look like on a proper website.

   EVERYTHING BELOW IS ADDED, NOT REWRITTEN. The rules above carry
   fixes that cost real time to find - the header rules anchored
   `> nav >` because the widget injects its own <ul> into the header,
   the footer's margin-top that has to out-specify the width rule,
   `.comps-fields` as the ACCOUNT details grid rather than a stat row.
   Layering on top keeps all of that; a rewrite would have quietly
   undone it.

   New classes are `comps-` prefixed like the rest, so pasting this
   page into a site that already has a .card or a .hero collides with
   nothing. ------------------------------------------------------ */

/* Type. One size fitted every heading; a site needs a scale, and one
   that holds up from a phone to a wide monitor. */
h1 { font-size: clamp(2rem, 1.2rem + 3.2vw, 3.3rem); font-weight: 780; letter-spacing: -.02em; line-height: 1.12; }
h2 { font-size: clamp(1.3rem, 1.05rem + 1vw, 1.8rem); font-weight: 700; letter-spacing: -.015em; }
body { font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
/* A webfont would look sharper still. Left commented because it puts
   a third-party request on your page, which is your call rather than
   ours - uncomment it and add the family to the stack above.
   @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"); */

/* The bar stays with you, and the name reads as a wordmark. */
body > header { position: sticky; top: 0; z-index: 20; }
body > header > nav > .site-name { display: inline-flex; align-items: center; gap: .55rem; font-size: 1.1rem; }
body > header > nav > .site-name::before {
  content: "";
  width: 1.5rem; height: 1.5rem; border-radius: 7px;
  background: linear-gradient(135deg, var(--page-accent), var(--page-accent-2));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
}

/* THE HERO IS THE ONE FULL-BLEED THING, so it has to opt out of the
   width rule above by name. A class beats any number of type
   selectors, so this wins wherever it sits in the file - unlike the
   footer's margin-top above, which had to be moved. */
body > .comps-hero {
  width: 100%; max-width: none; margin: 0;
  background:
    radial-gradient(90rem 40rem at 78% -20%, color-mix(in srgb, var(--page-accent-2) 32%, transparent), transparent 60%),
    linear-gradient(135deg, var(--hero-from), color-mix(in srgb, var(--page-accent-2) 45%, var(--hero-from)));
  color: var(--hero-ink);
  border: 0; border-radius: 0; box-shadow: none;
}
.comps-hero-inner {
  width: min(var(--page-width), 100% - 2rem);
  margin-inline: auto;
  padding: clamp(2.5rem, 1rem + 6vw, 4.75rem) 0 clamp(3rem, 1rem + 7vw, 5.25rem);
}
.comps-hero h1 { max-width: 16ch; margin-bottom: .75rem; }
.comps-hero p { font-size: clamp(1rem, .9rem + .5vw, 1.2rem); max-width: 52ch; opacity: .93; margin-bottom: 1.5rem; }
/* THE LIGHT (1.521.0) - green while a competition is running, red when
   none is.

   AN ATTRIBUTE, NOT A CLASS (1.532.0). The status widget sets
   data-state="live" | "idle" | "maintenance" on whichever element
   carries data-589comps-status, and invents no class of its own -
   a widget that added classes to your markup would be choosing your
   names for you. Until it has answered there is no attribute at all
   and the dot is grey, because a light that guesses is worse than
   one that waits.

   THE STATE IS NOT SCOPED TO ONE CARRIER. It was .comps-eyebrow, the
   hero pill, and the band over the competition carries .comps-live
   instead - so its light stayed grey while the pill's worked. The
   attribute goes on any element and the dot inside it follows. The
   pill itself went at 1.548.0; the rule outlived it because it was
   never about that one carrier.

   THE RING IS NOT DECORATION, AND IT MOVED WITH THE DOT (1.548.0).
   It was --hero-ink, measured against the hero pill: a tinted
   lozenge over the hero gradient, where a bare dot came out at
   1.06:1. The dot lives only in the band now, and --hero-ink against
   the band measures 1.15:1 in light and 1.13:1 in dark - a ring
   nobody can see. --page-ink is the band's own text colour and
   measures 14.4:1 and 14.0:1 on the same surface, so the light still
   reads as a light against whatever you recolour the band to. */
.comps-live-dot {
  width: .6rem; height: .6rem; border-radius: 50%; flex: none;
  background: var(--page-soft);
  outline: 2px solid var(--page-ink); outline-offset: 0;
}
[data-state="live"] .comps-live-dot {
  background: var(--page-live);
  animation: comps-pulse 2.4s ease-out infinite;
}
[data-state="idle"] .comps-live-dot { background: var(--page-idle); }
@keyframes comps-pulse {
  0% { box-shadow: 0 0 0 0 var(--page-live); }
  70% { box-shadow: 0 0 0 .45rem transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  [data-state="live"] .comps-live-dot { animation: none; }
}

/* THE COUNTDOWN, to this competition's finish while one runs and to
   the next one starting while none does. Hidden until there is
   something real to count to - no date, no clock, rather than an
   invented one.

   IT LIVES IN THE BAND NOW (1.535.0), and only there. The hero had a
   second copy of it until three clocks on one page was one too many;
   .comps-hero-count went with the markup, and these two classes
   stayed because the band's clock is built from them. */
.comps-count-label { font-size: .85rem; opacity: .85; }
.comps-count-value {
  font-size: clamp(1.3rem, 1.1rem + .9vw, 1.9rem); font-weight: 700;
  line-height: 1.1; font-variant-numeric: tabular-nums;
}
.comps-cta {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .75rem 1.3rem; margin-right: .6rem; border: 0; border-radius: 999px;
  background: var(--page-panel); color: var(--page-accent);
  font: inherit; font-weight: 680; text-decoration: none; cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
}
.comps-cta.comps-quiet { background: var(--hero-tint); color: var(--hero-ink); box-shadow: none; }

/* The competition lifted onto the hero rather than sitting under it.

   IT LIFTS THE BOARD NOW, NOT THE COMPETITION INSIDE IT (1.522.0).
   This was a negative margin on .comps-stage, from when the
   competition sat directly under the banner. With a heading and a
   live band above it the margin pulled the competition up OVER the
   band and drew across it - found by measuring the two boxes, not by
   looking, because both are dark and the overlap read as a gap.

   And it only applies where it means something: immediately after
   the banner. Delete the banner - which the board does not need -
   and nothing is lifted onto nothing. */
.comps-stage { position: relative; z-index: 1; }
.comps-hero + .comps-board { margin-top: clamp(-3.5rem, -2rem - 3vw, -2.25rem); position: relative; z-index: 1; }

/* ---- THE BOARD (1.522.0) --------------------------------------

   The competition, the heading over it and the live band between
   them. Asked for on 28 Sep 2026 with a screenshot of exactly this,
   pasted in by hand: "This is the layout I want to see on the test
   and live sites."

   TWO GRIDS, ONE RAIL WIDTH. This one holds the heading, the band
   and the competition; .comps-layout below - the markup in your
   saved layout - holds the picture and the cards. Both read
   --page-rail and --page-gap, which is the only thing keeping the
   band lined up with the picture rather than running on over the
   cards. */
.comps-board {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--page-rail);
  gap: 0 var(--page-gap);
  align-items: start;
}
/* The band belongs to the picture's column. The competition spans
   both, because its own layout splits them again.

   ROWS ARE STATED, NOT INFERRED. Left to auto-placement the
   competition landed in the same row as the band and drew straight
   over it - a full-width item and a column-pinned one do not queue
   the way they read. Two items, two rows, nothing to reason about.

   THERE WERE THREE until 1.535.0, when the heading we wrote over the
   competition went: "remove this from the templates, I didn't
   request this." Its rule and the two classes inside it went with
   the markup. */
.comps-live { grid-column: 1; grid-row: 1; }
.comps-board > [id^="comps-"] { grid-column: 1 / -1; grid-row: 2; }

/* THE LIVE BAND. It is joined to the picture's frame below it - one
   object with a lid - so the radius and the bottom border go. */
.comps-live {
  display: flex; align-items: center; gap: .65rem; flex-wrap: wrap;
  margin: 0; padding: .8rem 1.1rem;
  background: var(--page-bg-2);
  border: 1px solid var(--page-line);
  border-bottom: 0;
  border-radius: var(--page-radius) var(--page-radius) 0 0;
  color: var(--page-ink);
}
.comps-live-text { font-weight: 700; font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; }
.comps-live-title { color: var(--page-soft); font-size: .85rem; min-width: 0; overflow-wrap: anywhere; }
/* THE ROTATING FACTS. A divider before them rather than a character
   in the markup, so an empty span leaves no stray pipe behind - and
   a minimum width so the band does not jump about as each one is
   typed. 11em holds the longest of them at this size. */
.comps-live-facts {
  font-size: .85rem; color: var(--page-ink); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.comps-live-facts:not(:empty) {
  min-width: 11em;
  padding-left: .65rem; margin-left: .15rem;
  border-left: 1px solid var(--page-line);
}
.comps-live-count { display: flex; align-items: baseline; gap: .5rem; margin-left: auto; }
.comps-live-count[hidden] { display: none; }
.comps-live .comps-count-label { font-size: .78rem; color: var(--page-soft); }
.comps-live .comps-count-value { font-size: 1.15rem; font-weight: 700; color: var(--page-accent); font-variant-numeric: tabular-nums; }

/* ---- THE SAVED LAYOUT'S OWN MARKUP ------------------------------

   Everything from here down styles the markup in your Widget Layout,
   which Quick Start generates to match this stylesheet. Change one
   and change the other. None of it reaches inside either widget. */
.comps-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--page-rail);
  gap: var(--page-gap);
  align-items: start;
}
.comps-layout-main { min-width: 0; }

/* The picture, sitting under the band as one object. */
.comps-layout-frame {
  background: var(--page-panel);
  border: 1px solid var(--page-line);
  border-radius: 0 0 var(--page-radius) var(--page-radius);
  padding: .9rem;
  overflow: hidden;
}
.comps-layout-cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: .9rem; min-width: 0; align-content: start; }

.comps-card {
  background: var(--page-panel);
  border: 1px solid var(--page-line);
  border-radius: var(--page-radius);
  padding: .9rem 1rem;
}
.comps-card-title {
  margin: 0 0 .65rem; font-size: .72rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--page-soft);
}

/* label on the left, value on the right */
.comps-facts { list-style: none; margin: 0; padding: 0; }
.comps-fact {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: .75rem; padding: .38rem 0; border-bottom: 1px solid var(--page-line);
  font-size: .85rem;
}
.comps-fact:last-child { border-bottom: 0; }
.comps-k { color: var(--page-soft); }
.comps-v { text-align: right; overflow-wrap: anywhere; }

/* the counts */
.comps-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
.comps-tile { background: var(--page-bg-2); border-radius: calc(var(--page-radius) - 4px); padding: .65rem .35rem; text-align: center; }
.comps-tile-n { display: block; font-size: 1.3rem; line-height: 1.1; color: var(--page-accent); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.comps-tile-l { display: block; margin-top: .2rem; font-size: .62rem; letter-spacing: .04em; text-transform: uppercase; color: var(--page-soft); }

/* the feeds */
.comps-feed { list-style: none; margin: 0; padding: 0; }
.comps-feed-row {
  display: grid; grid-template-columns: fit-content(40%) minmax(0, 1fr);
  gap: .1rem .5rem; padding: .5rem 0;
  border-bottom: 1px solid var(--page-line); font-size: .82rem;
}
.comps-feed-row:last-child { border-bottom: 0; }
.comps-who { font-weight: 600; overflow-wrap: anywhere; }
.comps-what { color: var(--page-soft); overflow-wrap: anywhere; }
.comps-when { grid-column: 1 / -1; font-size: .72rem; color: var(--page-soft); opacity: .85; }


/* ---- A SLIDER IS A ROW, NOT A RAIL (1.524.0) --------------------

   Asked for on 28 Sep 2026: "When the slider option is selected it
   should appear directly under the competition area."

   The rail is 300px wide because a stack of cards reads well there.
   A slider does not: it is one card at a time with arrows on its
   edges, and in a 300px column it was both cramped and - because the
   widget sizes it from its content - spilling off the page.

   So when the cards are a slider the grid drops to ONE column: the
   picture takes the full width, the band above it follows, and the
   slider sits directly beneath. The board is matched as well as the
   layout because the two grids are meant to stay in step - see
   --page-rail.

   is-slider IS THE WIDGET'S OWN CONTRACT CLASS, not a new name: the
   generated markup carries it, and a partner who writes their own
   markup adds or removes it to the same effect. It is only ever used
   here compounded with a comps- class, so it cannot catch a class of
   the partner's that happens to share the name.

   NO MARKUP CHANGED FOR THIS. A template already saved gets the new
   arrangement on its next page load, with no regenerate and nothing
   orphaned. Where :has() is not supported the cards stay in the rail,
   which is exactly what they do today. */
.comps-board:has(.comps-layout-cards.is-slider),
.comps-layout:has(> .comps-layout-cards.is-slider) {
  grid-template-columns: minmax(0, 1fr);
}

/* ONE BREAKPOINT, AND IT IS ABOUT THE RAIL. Below this the cards go
   under the picture instead of beside it. It touches nothing in the
   header - where a width cannot be chosen, because it depends on how
   long the partner's site name is. */
@media (max-width: 56rem) {
  .comps-board, .comps-layout { grid-template-columns: minmax(0, 1fr); }
}

/* How it works, and anything else wanting even columns. */
.comps-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.comps-step { background: var(--page-bg-2); border: 1px solid var(--page-line); border-radius: var(--page-radius); padding: 1.15rem; }
.comps-step h3 { color: var(--page-ink); text-transform: none; letter-spacing: normal; font-size: 1.02rem; margin-bottom: .35rem; }
.comps-step p { margin: 0; color: var(--page-soft); }
.comps-step-n {
  display: inline-grid; place-items: center; width: 2rem; height: 2rem; margin-bottom: .65rem;
  border-radius: 8px; font-weight: 700; font-size: .9rem;
  background: var(--page-accent); color: var(--page-accent-ink);
}
.comps-lede { color: var(--page-soft); max-width: 60ch; margin: -.2rem 0 1.3rem; }

/* The footer reads as the end of a site rather than a line of text. */
body > footer:last-of-type { background: var(--page-bg-2); }

body > header, body > header *,
body > .comps-hero, body > .comps-hero *,
body > section, body > section *,
body > div[id^="comps-"],
body > footer, body > footer * {
  box-sizing: border-box;
}

body > header > nav { flex-wrap: wrap; row-gap: .35rem; padding-block: .45rem; }
body > header > nav > .site-name { white-space: normal; min-width: 0; }
body > header > nav > ul { flex: 1 1 18rem; width: auto; }