@import "tailwindcss";

/* Geist, variable — one file covers every weight, 68 KB. Checked against the
   Serbian alphabet before it was chosen: Č č Ć ć Š š Ž ž Đ đ are all present.
   Đ (U+0110) is the one that fashionable typefaces usually drop, and a site that
   cannot write Đorđe is not a Serbian site. SIL Open Font License. */
@font-face {
  font-family: "Geist";
  src: url("/assets/Geist-Variable-b11a6485.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Geist Mono";
  src: url("/assets/GeistMono-Variable-6dd1dc09.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@theme {
  --font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", monospace;

  /* Warm-neutral greys, pale end first, the way every other scale runs: 50 is
     the page and 950 is the type. */
  --color-carbon-50: #f7f7f5;
  --color-carbon-100: #f0f0ed;
  --color-carbon-150: #e9e9e5;
  --color-carbon-200: #dededa;
  --color-carbon-300: #cbcbc6;
  --color-carbon-400: #b0b0aa;
  --color-carbon-500: #8a8a85;
  --color-carbon-600: #6b6b66;
  --color-carbon-700: #51514d;
  --color-carbon-800: #3a3a37;
  --color-carbon-900: #262624;
  --color-carbon-950: #141413;

  /* One accent: navy. Chosen off five blues walked through on real pages. It
     carries the headline, the primary action, the current page and the active
     tab.

     Three variables rather than two: the shadow under the button has to be the
     accent at low alpha, and a hex cannot be given one, so --accent-rgb holds
     the same colour as bare channels for rgb(var(--accent-rgb) / 0.35). Keep
     them in step if the colour ever moves again. */
  --color-accent: #1e3a8a;
  --color-accent-deep: #162d6e;
  --accent-rgb: 30 58 138;

  /* Medals are content, not theme. Gold-silver-bronze stays on the podium, but
     muted to metal rather than paint — the taxi yellow went with the old accent. */
  --color-medal-gold: #d9b24c;
  --color-medal-silver: #c9c9c4;
  --color-medal-bronze: #b58157;

  --color-flame-500: #e8112d;
  --color-sky-500: #0e9fd8;

  /* What a template actually means — the text colour, a hairline, a wash — so
     the markup never bakes in a value it cannot defend. Ink is graphite, not
     black: the same family as the button, one step darker than the body, so the
     page is soft without going grey. */
  --color-ink: #33332f;
  --color-line: rgba(0, 0, 0, 0.1);
  --color-wash-1: rgba(0, 0, 0, 0.02);
  --color-wash-2: rgba(0, 0, 0, 0.045);
  --color-wash-3: rgba(0, 0, 0, 0.08);
}


@layer base {
  html {
    scroll-behavior: smooth;
    background-color: var(--color-carbon-50);
  }

  body {
    font-feature-settings: "cv11", "ss01";
  }

  ::selection {
    background-color: var(--color-accent);
    color: #ffffff;
  }

  :focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
  }
}

/* Declared with @utility rather than as plain classes, because Tailwind 4 will
   only let @apply reach a real utility — and the components below apply them. */

/* Every number on this site is a measurement compared against the number above
   it — a score, a rank, a date. Tabular lining figures keep the columns true,
   and the mono face says "this is data" before anyone has read a digit. */
@utility num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.01em;
}

/* Headlines only. At display sizes the default tracking opens up and the words
   stop holding together as a shape. */
@utility display {
  letter-spacing: -0.035em;
  line-height: 1.02;
}

/* The weave itself. One 20 px tile from app/assets/images/carbon.svg, repeated.
   Kept as a file rather than inlined so the pattern stays legible and editable —
   it is a drawing, and a drawing encoded into a CSS string stops being one. */
@utility carbon-weave {
  background-image: url("/assets/carbon-b5ce3b4d.svg");
  background-size: 20px 20px;
  background-repeat: repeat;
}

@layer components {
  /* The surface the whole archive is printed on: almost black where the reading
     happens, turning into carbon as it falls away.

     Lit from one corner rather than evenly. An even vignette reads as a vignette
     — a photographic effect applied to a page. A single light reads as a surface
     with a direction, which is what a bow limb under a lamp actually looks like.

     Two layers, both fixed: the page moves, the surface it is printed on does
     not. The colour lives on <html>, because giving <body> a background of its
     own paints straight over z-index -1 — which is exactly how this was
     invisible the first time.

     ::before is the weave, held back by two masks at once. The ellipse keeps it
     out of the middle where the reading happens; the reach keeps it near the
     lamp. Intersected, so fibre survives only where both agree — at an edge, and
     in the light. One mask alone gives either a symmetrical ring or a woven page.

     The reach is radial from the corner, not a diagonal ramp. A ramp treats the
     other two corners as half-lit, because they are halfway along it — and they
     came out visibly brighter than they should be. Light falls off with distance
     from where it is, so the far corners have to be dark in every direction at
     once, which only a radial does.

     Two lamps: the main one top right, and a much fainter one top left — enough
     that the far side is not dead, not enough to read as a second source. They are added to
     each other first and the edge is intersected with the sum, so fibre needs an
     edge and at least one lamp. Composited in that order because a mask layer
     combines with everything listed after it, not before. */
  .carbon-surface::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background-image: url("/assets/carbon-b5ce3b4d.svg");
    background-size: 20px 20px;
    -webkit-mask-image:
      radial-gradient(ellipse 82% 74% at 50% 42%, transparent 28%, rgba(0, 0, 0, 0.55) 66%, #000 100%),
      radial-gradient(72% 68% at 99% -2%, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.3) 32%, transparent 62%),
      radial-gradient(44% 42% at 0% 2%, rgba(0, 0, 0, 0.17) 0%, rgba(0, 0, 0, 0.07) 32%, transparent 62%);
    mask-image:
      radial-gradient(ellipse 82% 74% at 50% 42%, transparent 28%, rgba(0, 0, 0, 0.55) 66%, #000 100%),
      radial-gradient(72% 68% at 99% -2%, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.3) 32%, transparent 62%),
      radial-gradient(44% 42% at 0% 2%, rgba(0, 0, 0, 0.17) 0%, rgba(0, 0, 0, 0.07) 32%, transparent 62%);
    -webkit-mask-composite: source-in, source-over;
    mask-composite: intersect, add;
    pointer-events: none;
  }

  /* ::after is the light itself. On a pale page the bloom is nearly invisible —
     the lamp shows through where the weave gathers — and the shade opposite has
     to stay a breath, not a stain: what reads as shadow on black reads as dirt
     on white. */
  .carbon-surface::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background-image:
      radial-gradient(60% 48% at 94% -8%, rgba(255, 255, 255, 0.042), transparent 58%),
      radial-gradient(38% 32% at 2% 0%, rgba(255, 255, 255, 0.008), transparent 60%),
      radial-gradient(95% 75% at 20% 112%, rgba(0, 0, 0, 0.13), transparent 60%);
    pointer-events: none;
  }

  /* The quiet workhorse: a row in a list of results. The hover is a wash rather
     than a border so a long list does not jump by a pixel as the mouse crosses
     it. */
  .row {
    @apply -mx-3 flex items-baseline gap-4 rounded-lg px-3 py-2.5 transition-colors;
  }

  .row:hover {
    @apply bg-wash-2;
  }

  /* Rank badges. Gold, silver and bronze are the one piece of visual shorthand
     every single visitor already knows, archer or not. */
  .rank {
    @apply num inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-xs font-medium;
    @apply bg-wash-2 text-carbon-600;
  }

  .rank-1 { @apply bg-medal-gold text-carbon-950; }
  .rank-2 { @apply bg-medal-silver text-carbon-950; }
  .rank-3 { @apply bg-medal-bronze text-carbon-50; }

  .field {
    @apply rounded-lg border border-carbon-200 bg-white px-3.5 py-2 text-sm text-carbon-800 shadow-xs transition;
    @apply placeholder:text-carbon-500;
  }

  .field:focus {
    @apply border-accent outline-none;
  }

  /* Dark select menus still draw their options from the system, so the options
     themselves have to be told as well or they come out white-on-white. */
  .field option {
    @apply bg-carbon-150 text-carbon-900;
  }

  /* The primary action is ink — dark and colourless. The crimson stays for the
     small signals (the eyebrow, the disputed flag, focus); an action does not
     need a colour, it needs weight. The inset highlight along the top edge and
     the shadow are what separate a button from a rectangle filled with dark:
     lit from above, resting on the page. */
  /* The primary action wears the accent — that is what makes it the primary
     action. The inset highlight along the top edge and the tinted shadow are
     what separate a button from a rectangle filled with colour: lit from above,
     resting on the page. */
  .btn {
    @apply rounded-lg bg-accent px-4 py-2 text-sm font-semibold text-white transition-all;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgb(var(--accent-rgb) / 0.35);
  }

  .btn:hover {
    @apply bg-accent-deep;
  }

  .btn:active {
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
    transform: translateY(0.5px);
  }

  /* Pagination. pagy marks the current page with aria-current and the gaps with
     role=separator, so the state is styled off what the markup already says
     rather than off classes it does not have. */
  .pagy {
    @apply num flex flex-wrap items-center gap-1 text-sm;
  }

  .pagy a {
    @apply rounded-lg px-3 py-1.5 text-carbon-600 transition-colors;
  }

  .pagy a[href]:hover {
    @apply bg-wash-2 text-ink;
  }

  .pagy a[aria-current="page"] {
    @apply bg-accent font-medium text-white;
  }

  .pagy a[role="separator"] {
    @apply text-carbon-400;
  }

  /* A panel that sits above the surface: slightly lighter, hairline edge. No
     shadow — on a black page a shadow is invisible and only costs paint. */
  .panel {
    @apply rounded-2xl border border-carbon-200/70 bg-white shadow-xs;
  }
}
