/* ===========================================================================
   BACKPACK — the design system for every game on this site.

   Tokens and components taken from Skyscanner's Backpack (Apache-2.0,
   github.com/Skyscanner/backpack-foundations, packages/bpk-foundations-web).
   Every value below is the system's own; none of it was eyeballed.

   TWO RULES, and the gate enforces both.

   1. Everything here is namespaced — `--bpk-*` for tokens, `.bpk-*` for
      components. There is not one bare element selector in this file. A game
      that has not been migrated yet can load it and look exactly as it did:
      that is what makes migrating thirty-one games one at a time possible.

   2. A game must not redeclare a token this file owns. To change the system,
      change this file. A game declares only `--game-flavour` — its one colour,
      for an illustration tint and a single header rule. Never a button, never
      a state: a control that is a different colour in every game is not a
      system, and an answer button tinted differently from its sibling tells
      the player which one to press.
   =========================================================================== */

:root {
  /* ---- canvas and surfaces (SURFACE_*, CANVAS_*) ---- */
  --bpk-canvas: #FFFFFF;
  --bpk-canvas-contrast: #EFF3F8;
  --bpk-surface-default: #FFFFFF;
  --bpk-surface-elevated: #FFFFFF;
  --bpk-surface-subtle: #E3F0FF;
  --bpk-surface-highlight: #E0E4E9;
  --bpk-surface-low-contrast: #F5F7FA;
  --bpk-surface-contrast: #05203C;
  --bpk-surface-hero: #0062E3;

  /* ---- core and text (CORE_*, TEXT_*) ---- */
  --bpk-core-accent: #0062E3;
  --bpk-core-primary: #05203C;
  /* CORE_ECO, published with the same value for day and night, which is why it
     is declared once. A chart with two series needs two colours that mean
     something: these two are the pair. */
  --bpk-core-eco: #0FA1A9;
  --bpk-series-1: var(--bpk-core-accent);
  --bpk-series-2: var(--bpk-core-eco);
  --bpk-text-primary: #161616;
  --bpk-text-secondary: #626971;
  --bpk-text-disabled: rgba(0, 0, 0, .2);
  --bpk-text-link: #0062E3;
  --bpk-text-on-dark: #FFFFFF;
  /* The accent is a deep blue by day and a light cyan by night, so a label on
     top of it has to flip with the theme. One token, so no component has to
     know which theme it is in. */
  --bpk-text-on-accent: #FFFFFF;
  --bpk-text-on-fill: #05203C;   /* status fills stay light at night, so this does not flip */
  --bpk-text-error: #E70866;
  --bpk-line: #C1C7CF;
  --bpk-scrim: rgba(0, 0, 0, .7);

  /* ---- status (STATUS_*_SPOT / _FILL) ---- */
  --bpk-success: #0C838A;  --bpk-success-fill: #D4FFF2;
  --bpk-warning: #F55D42;  --bpk-warning-fill: #FFF7CF;
  --bpk-danger:  #E70866;  --bpk-danger-fill:  #FFE9F9;

  /* ---- spacing (SPACING_*) ---- */
  --bpk-sp-xxs: .0625rem; --bpk-sp-xs: .125rem; --bpk-sp-sm: .25rem;
  --bpk-sp-md: .5rem;     --bpk-sp-base: 1rem;  --bpk-sp-lg: 1.5rem;
  --bpk-sp-xl: 2rem;      --bpk-sp-xxl: 2.5rem; --bpk-sp-xxxl: 4rem;

  /* ---- radii and borders (BORDER_*) ---- */
  --bpk-radius-xs: .25rem; --bpk-radius-sm: .5rem; --bpk-radius-md: .75rem;
  --bpk-radius-lg: 1.5rem; --bpk-radius-xl: 2.5rem;
  --bpk-border-sm: 1px; --bpk-border-lg: 2px; --bpk-border-xl: 3px;

  /* ---- type (FONT_*) ----
     Backpack's own stacks, with one addition. The brand faces are licensed and
     are not in the open-source repo, so `Skyscanner Relative` and `Larken`
     resolve for nobody until their woff2 files are self-hosted beside this file.
     They stay first in the stack so that dropping those files in is a one-line
     change — and Inter sits behind them as the stand-in, because falling
     straight through to the system stack would make thirty-one pages look
     unstyled rather than on-brand.

     Inter and not Figtree, although all thirty-one games already asked for
     Figtree. Two reasons. It is a neo-grotesque, which is the family Relative
     belongs to and which the rest of Backpack's own fallback stack is made of
     (-apple-system, Roboto, Segoe UI) — Figtree is a rounded geometric, a
     different thing wearing the same label. And Figtree draws a euro sign whose
     crossbars overrun its advance width, so at display weights "€58" fused into
     a single shape; several of these games are about a number with a currency
     symbol in front of it. Inter sets the same string cleanly at 900.

     There is no serif stand-in for Larken on purpose. Larken is a brand-
     expression face; Backpack's product surfaces set their headlines in
     Relative at the heavy weights, which is what a game is. Guessing at a
     serif would be inventing a brand decision rather than following one. */
  --bpk-font-base: 'Skyscanner Relative', 'Inter', -apple-system, BlinkMacSystemFont,
                   'Roboto', 'Segoe UI', 'Helvetica Neue', sans-serif;
  --bpk-font-display: 'Larken', 'Skyscanner Relative', 'Inter', -apple-system,
                      BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --bpk-size-xs: .75rem;  --bpk-size-sm: .875rem; --bpk-size-base: 1rem;
  --bpk-size-lg: 1.25rem; --bpk-size-xl: 1.5rem;  --bpk-size-xxl: 2rem;
  --bpk-size-xxxl: 2.5rem; --bpk-size-xxxxl: 3rem; --bpk-size-5xl: 4rem;
  --bpk-weight-light: 300; --bpk-weight-book: 400;
  --bpk-weight-bold: 700;  --bpk-weight-black: 900;
  /* For headlines made of words. Not for figures: at display sizes -0.04em ran
     a euro sign into the digit beside it, and a price is the one thing several
     of these games are actually about. Big numbers get .bpk-num instead. */
  --bpk-tracking-hero: -.04em;

  /* ---- motion (DURATION_*) ---- */
  --bpk-dur-xs: 50ms; --bpk-dur-sm: 200ms; --bpk-dur-base: 400ms;

  /* ---- elevation: surface colour and a soft lift, never a drawn offset ---- */
  --bpk-shadow-sm: 0 1px 2px rgba(5, 32, 60, .08);
  --bpk-shadow-lg: 0 2px 8px rgba(5, 32, 60, .12), 0 8px 24px rgba(5, 32, 60, .08);

  /* ---- illustration ----
     Backpack's illustrations are drawn in the brand navy over a soft ground,
     with one accent. These are DERIVED, not quoted: `ink` is CORE_PRIMARY by day
     and SURFACE_SUBTLE's blue by night, because CORE_PRIMARY at night is a deep
     navy that vanishes against a night card. Said plainly here so nobody later
     mistakes them for values Backpack publishes.

     The ground carries a little of the game's own colour. That is not
     decoration: a drawing needs three values that differ — ground, silhouette,
     highlight — and a ground of flat #F5F7FA sat too close to a white highlight,
     so snow on a mountain merged into the sky and the peak read as forked. The
     flat value is declared first as the fallback for a browser without
     color-mix(). */
  --bpk-illustration-ink: #05203C;
  --bpk-illustration-ground: #F5F7FA;
  --bpk-illustration-ground: color-mix(in srgb, var(--game-flavour) 9%, #F5F7FA);
  --bpk-illustration-highlight: #FFFFFF;
  --game-flavour-text: color-mix(in srgb, var(--game-flavour) 45%, #FFFFFF);

  /* A game sets this to its own colour. Used for an illustration tint and one
     header rule — nothing a player clicks.

     --game-flavour-text is the same colour made safe to set WORDS in. A flavour
     is picked against a white page, and most of them land around 2.7:1 on a
     night canvas, so anywhere the colour is type rather than a block, use this. */
  --game-flavour: var(--bpk-core-accent);
  --game-flavour-text: var(--game-flavour);
}

/* Night. Both forms, matching how every game on this site already does it:
   the media query for viewers who never chose, the attribute for the toggle. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bpk-canvas: #010913;
    --bpk-canvas-contrast: #010913;
    --bpk-surface-default: #131D2B;
    --bpk-surface-elevated: #243346;
    --bpk-surface-subtle: #243346;
    --bpk-surface-highlight: #243346;
    --bpk-surface-low-contrast: #243346;
    --bpk-surface-contrast: #010913;
    --bpk-surface-hero: #010913;
    --bpk-core-accent: #84E9FF;
    --bpk-core-primary: #054184;
    --bpk-text-primary: #FFFFFF;
    --bpk-text-secondary: #BDC4CB;
    --bpk-text-disabled: rgba(255, 255, 255, .2);
    --bpk-text-link: #84E9FF;
    --bpk-text-on-accent: #010913;
    --bpk-text-error: #FF649C;
    --bpk-line: #44505F;
    --bpk-success: #62F1C6; --bpk-success-fill: #B1FFE7;
    --bpk-warning: #FEEB87; --bpk-warning-fill: #FBF1BB;
    --bpk-danger:  #FF649C; --bpk-danger-fill:  #FFCADD;
    --bpk-illustration-ink: #E3F0FF;
    --bpk-illustration-ground: #243346;
    --bpk-illustration-ground: color-mix(in srgb, var(--game-flavour) 16%, #243346);
    --bpk-illustration-highlight: #FFFFFF;
  --game-flavour-text: color-mix(in srgb, var(--game-flavour) 45%, #FFFFFF);
    --game-flavour-text: color-mix(in srgb, var(--game-flavour) 45%, #FFFFFF);
    --bpk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --bpk-shadow-lg: 0 2px 8px rgba(0, 0, 0, .5), 0 8px 24px rgba(0, 0, 0, .35);
  }
}
:root[data-theme="dark"] {
  --bpk-canvas: #010913;
  --bpk-canvas-contrast: #010913;
  --bpk-surface-default: #131D2B;
  --bpk-surface-elevated: #243346;
  --bpk-surface-subtle: #243346;
  --bpk-surface-highlight: #243346;
  --bpk-surface-low-contrast: #243346;
  --bpk-surface-contrast: #010913;
  --bpk-surface-hero: #010913;
  --bpk-core-accent: #84E9FF;
  --bpk-core-primary: #054184;
  --bpk-text-primary: #FFFFFF;
  --bpk-text-secondary: #BDC4CB;
  --bpk-text-disabled: rgba(255, 255, 255, .2);
  --bpk-text-link: #84E9FF;
  --bpk-text-on-accent: #010913;
  --bpk-text-error: #FF649C;
  --bpk-line: #44505F;
  --bpk-success: #62F1C6; --bpk-success-fill: #B1FFE7;
  --bpk-warning: #FEEB87; --bpk-warning-fill: #FBF1BB;
  --bpk-danger:  #FF649C; --bpk-danger-fill:  #FFCADD;
  --bpk-illustration-ink: #E3F0FF;
  --bpk-illustration-ground: #243346;
  --bpk-illustration-ground: color-mix(in srgb, var(--game-flavour) 16%, #243346);
  --bpk-illustration-highlight: #FFFFFF;
  --game-flavour-text: color-mix(in srgb, var(--game-flavour) 45%, #FFFFFF);
  --bpk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --bpk-shadow-lg: 0 2px 8px rgba(0, 0, 0, .5), 0 8px 24px rgba(0, 0, 0, .35);
}

/* ===========================================================================
   Components. Opt-in classes only — adding this file to a page changes nothing
   until the page asks for a class.
   =========================================================================== */

/* ---- page ---- */
.bpk-page { background: var(--bpk-canvas-contrast); color: var(--bpk-text-primary);
  font-family: var(--bpk-font-base); font-size: var(--bpk-size-base); line-height: 1.5; }
.bpk-wrap { max-width: 46rem; margin-inline: auto; padding-inline: var(--bpk-sp-base); }

/* ---- type ---- */
.bpk-hero { margin: 0; font-family: var(--bpk-font-display); font-weight: var(--bpk-weight-black);
  font-size: clamp(2rem, 8vw, var(--bpk-size-5xl)); line-height: 1.05;
  letter-spacing: var(--bpk-tracking-hero); text-wrap: balance; }
.bpk-h1 { margin: 0; font-family: var(--bpk-font-display); font-weight: var(--bpk-weight-bold);
  font-size: clamp(1.75rem, 6vw, var(--bpk-size-xxxl)); line-height: 1.1; text-wrap: balance; }
.bpk-h2 { margin: 0; font-weight: var(--bpk-weight-bold); font-size: var(--bpk-size-xl); line-height: 1.2; }
.bpk-h3 { margin: 0; font-weight: var(--bpk-weight-bold); font-size: var(--bpk-size-lg); line-height: 1.25; }
.bpk-body { font-size: var(--bpk-size-base); }
.bpk-caption { font-size: var(--bpk-size-sm); color: var(--bpk-text-secondary); }
.bpk-footnote { font-size: var(--bpk-size-xs); color: var(--bpk-text-secondary); }
.bpk-label { font-size: var(--bpk-size-xs); font-weight: var(--bpk-weight-bold);
  letter-spacing: .08em; text-transform: uppercase; color: var(--bpk-text-secondary); }
.bpk-num { font-variant-numeric: tabular-nums; }

/* ---- the one place a game's own colour shows in the chrome ---- */
.bpk-flavour-rule { height: var(--bpk-border-xl); background: var(--game-flavour);
  border-radius: var(--bpk-radius-xs); }

/* ---- buttons ----
   Hover changes colour, never position: a lift moves the hit area off a resting
   pointer and the button jitters. check-games.py fails any rule that moves one. */
.bpk-btn { display: inline-flex; align-items: center; justify-content: center;
  gap: var(--bpk-sp-md); min-height: 2.75rem; padding: var(--bpk-sp-md) var(--bpk-sp-lg);
  border: var(--bpk-border-lg) solid transparent; border-radius: var(--bpk-radius-sm);
  font: inherit; font-weight: var(--bpk-weight-bold); line-height: 1.2; text-align: center;
  text-decoration: none; cursor: pointer; background: var(--bpk-surface-default);
  color: var(--bpk-text-primary); transition: background-color var(--bpk-dur-sm),
  border-color var(--bpk-dur-sm), box-shadow var(--bpk-dur-sm); }
.bpk-btn--primary { background: var(--bpk-core-accent); color: var(--bpk-text-on-accent);
  border-color: var(--bpk-core-accent); }
.bpk-btn--primary:hover { background: var(--bpk-core-primary); border-color: var(--bpk-core-primary);
  color: var(--bpk-text-on-dark); }
.bpk-btn--secondary { background: var(--bpk-surface-default); color: var(--bpk-text-link);
  border-color: var(--bpk-line); }
.bpk-btn--secondary:hover { border-color: var(--bpk-core-accent); background: var(--bpk-surface-subtle); }
.bpk-btn--link { background: none; border-color: transparent; color: var(--bpk-text-link);
  padding-inline: var(--bpk-sp-sm); text-decoration: underline; text-underline-offset: 3px; }
.bpk-btn--destructive { background: var(--bpk-danger); color: #FFFFFF; border-color: var(--bpk-danger); }
.bpk-btn--wide { width: 100%; }
.bpk-btn[disabled], .bpk-btn[aria-disabled="true"] { opacity: .4; cursor: not-allowed; }

/* ---- focus: one ring, everywhere, visible on both canvases ---- */
.bpk-btn:focus-visible, .bpk-chip:focus-visible, .bpk-input:focus-visible,
.bpk-card:focus-visible, a:focus-visible .bpk-card {
  outline: var(--bpk-border-xl) solid var(--bpk-core-accent); outline-offset: 2px; }

/* ---- chips (toggles) ---- */
.bpk-chip { display: inline-flex; align-items: center; gap: var(--bpk-sp-sm);
  min-height: 2.5rem; padding: var(--bpk-sp-md) var(--bpk-sp-base);
  border: var(--bpk-border-sm) solid var(--bpk-line); border-radius: var(--bpk-radius-xl);
  background: var(--bpk-surface-default); color: var(--bpk-text-primary);
  font: inherit; font-weight: var(--bpk-weight-bold); cursor: pointer;
  transition: background-color var(--bpk-dur-sm), border-color var(--bpk-dur-sm); }
.bpk-chip[aria-pressed="true"] { background: var(--bpk-surface-subtle);
  border-color: var(--bpk-core-accent); color: var(--bpk-text-link); }
.bpk-chip[disabled] { opacity: .4; cursor: not-allowed; }

/* ---- surfaces ---- */
.bpk-card { background: var(--bpk-surface-default); border: var(--bpk-border-sm) solid var(--bpk-line);
  border-radius: var(--bpk-radius-lg); padding: var(--bpk-sp-base); box-shadow: var(--bpk-shadow-sm); }
.bpk-card--elevated { background: var(--bpk-surface-elevated); box-shadow: var(--bpk-shadow-lg); border-color: transparent; }
.bpk-card--subtle { background: var(--bpk-surface-subtle); border-color: transparent; box-shadow: none; }
.bpk-card--hero { background: var(--bpk-surface-hero); color: var(--bpk-text-on-dark); border-color: transparent; }
.bpk-card--contrast { background: var(--bpk-surface-contrast); color: var(--bpk-text-on-dark); border-color: transparent; }
.bpk-divider { height: var(--bpk-border-sm); background: var(--bpk-line); border: 0; }

/* ---- inputs ---- */
.bpk-input, .bpk-select { width: 100%; min-height: 2.75rem; padding: var(--bpk-sp-md) var(--bpk-sp-base);
  border: var(--bpk-border-lg) solid var(--bpk-line); border-radius: var(--bpk-radius-sm);
  background: var(--bpk-surface-default); color: var(--bpk-text-primary); font: inherit; }
.bpk-input:focus, .bpk-select:focus { border-color: var(--bpk-core-accent); outline: none; }
.bpk-input[aria-invalid="true"] { border-color: var(--bpk-text-error); }

/* ---- status ---- */
.bpk-status { display: inline-flex; align-items: center; gap: var(--bpk-sp-md);
  padding: var(--bpk-sp-md) var(--bpk-sp-base); border-radius: var(--bpk-radius-sm);
  font-weight: var(--bpk-weight-bold); }
.bpk-status--success { background: var(--bpk-success-fill); color: var(--bpk-text-on-fill); }
.bpk-status--warning { background: var(--bpk-warning-fill); color: var(--bpk-text-on-fill); }
.bpk-status--danger  { background: var(--bpk-danger-fill);  color: var(--bpk-text-on-fill); }

/* ---- sheet / dialog ---- */
.bpk-scrim-layer { position: fixed; inset: 0; background: var(--bpk-scrim); z-index: 50;
  display: flex; align-items: flex-end; justify-content: center; }
.bpk-sheet { width: 100%; max-width: 34rem; max-height: 92dvh; overflow: auto;
  background: var(--bpk-surface-elevated); color: var(--bpk-text-primary);
  border-radius: var(--bpk-radius-lg) var(--bpk-radius-lg) 0 0;
  padding: var(--bpk-sp-lg) var(--bpk-sp-base) calc(var(--bpk-sp-lg) + env(safe-area-inset-bottom, 0px));
  box-shadow: var(--bpk-shadow-lg); }
@media (min-width: 40rem) {
  .bpk-scrim-layer { align-items: center; }
  .bpk-sheet { border-radius: var(--bpk-radius-lg); padding: var(--bpk-sp-lg); }
}

/* ---- tables: figures line up, headers read as headers ---- */
.bpk-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.bpk-table th, .bpk-table td { padding: var(--bpk-sp-md) var(--bpk-sp-base);
  border-bottom: var(--bpk-border-sm) solid var(--bpk-line); text-align: left; }
.bpk-table th { font-size: var(--bpk-size-xs); font-weight: var(--bpk-weight-bold);
  letter-spacing: .08em; text-transform: uppercase; color: var(--bpk-text-secondary); }

/* ---- illustration ----
   Generated art is drawn with THREE fills and no literal hex: `art-ink` for the
   structure that carries the drawing, `art-tint` for the game's one colour, and
   `art-ground` for the sky behind it. A silhouette in a hard-coded dark hex
   disappears on a night card; these three flip with the theme by themselves.
   A class is the cheapest way in, but `fill="var(--bpk-text-secondary)"` works
   too — a presentation attribute is parsed as a CSS value, so var() resolves
   there (checked in the probe browser, both forms compute the same fill).

   This is for drawings a game generates. A photographic or brand illustration
   belongs in an <img>, and never in place of a drawing that is doing a job —
   a diagram of a seat row, a baggage sizer, a boarding pass — because those
   are the content, not decoration around it. */
.bpk-art { background: var(--bpk-illustration-ground); overflow: hidden; }
.bpk-art svg { display: block; width: 100%; height: 100%; }
.art-ink { fill: var(--bpk-illustration-ink); }
.art-tint { fill: var(--game-flavour); }
.art-ground { fill: var(--bpk-illustration-ground); }
/* Snow, cloud, a sun: the lightest value in the drawing. It reads on the ink and
   on the tint, and it is NOT the ground — a highlight the colour of the sky
   merges with the sky wherever the two touch. */
.art-highlight { fill: var(--bpk-illustration-highlight); }
.art-ink-line { stroke: var(--bpk-illustration-ink); fill: none; }
/* stroke only, for a shape that also has a fill of its own */
.art-stroke { stroke: var(--bpk-illustration-ink); }

/* ---- the honesty furniture, so it is a component and not a footnote a
        redesign can quietly drop ---- */
.bpk-illustrative { display: inline-flex; align-items: center; gap: var(--bpk-sp-sm);
  padding: var(--bpk-sp-sm) var(--bpk-sp-md); border: var(--bpk-border-sm) dashed var(--bpk-line);
  border-radius: var(--bpk-radius-md); font-size: var(--bpk-size-xs); color: var(--bpk-text-secondary);
  max-width: 100%; line-height: 1.35; }
.bpk-source { font-size: var(--bpk-size-xs); color: var(--bpk-text-secondary); line-height: 1.45; }

.bpk-sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .bpk-btn, .bpk-chip, .bpk-input, .bpk-select { transition-duration: .001ms !important; }
}
