/* ========================================================================= */
/* WHAT THIS FILE IS (in plain English):                                     */
/*                                                                           */
/* The house style for every Waygate web page. Think of it as the uniform:   */
/* one set of colours, one set of letter sizes, one way a button, a card or  */
/* a heading looks. Each page wears this first, then adds only what is truly */
/* its own (the Runecast's slot grid, the Bazaar's price tags) in its own    */
/* <style> block.                                                            */
/*                                                                           */
/* Before this file existed, every page carried a private copy of the same   */
/* rules, and the copies drifted: some labels shrank to 7 pixels, headings   */
/* sat in three different places, and the Hub button covered titles on a     */
/* phone. One copy cannot drift from itself.                                 */
/*                                                                           */
/* This is CSS ("Cascading Style Sheets"), the language for how a page       */
/* LOOKS. A rule is a "selector" (which things) and a block in { } (how they */
/* look). Comments are the text between slash-star and star-slash.           */
/*                                                                           */
/* The rules a page must follow are checked in CI by                          */
/* tools/check_web_style.py, and written out in docs/web-style.md.           */
/* ========================================================================= */


/* ── 1. THE TOKENS ─────────────────────────────────────────────────────────
   Names starting with -- are "CSS variables" (here called tokens): a value
   given a name once, then used everywhere by name. Change one here and every
   page follows. ":root" is the whole document, so these names reach every
   rule on every page. */
:root {
  /* Colours. Hex codes mix Red, Green and Blue, two digits each. */
  --void: #06080c;          /* the page background: nearly black */
  --obsidian: #0d1015;      /* a raised surface: cards, slots */
  --well: #0a0d12;          /* a sunken surface: inputs, inner boxes */
  --line: #1a2330;          /* hairline borders */
  --parchment: #e9e7df;     /* main text */
  --ash: #8a93a2;           /* quieter text: hints, labels */
  --gold: #c9a24b;          /* the accent: buttons, section names */
  --gold-bright: #e6c479;   /* the accent at its brightest: titles */
  --rune: #3f93c4;          /* the second accent: links, magic */
  /* The rune blue at its brightest (link text), and at its deepest (shadows). */
  --rune-bright: #6ab8e6;
  --rune-deep: #1c567c;
  --ember: #c98a6b;         /* warnings and apologies */
  --heal: #7fb069;          /* success */
  --blood: #b8564f;         /* danger */
  /* The danger red, brighter, for text that must stand out. */
  --blood-bright: #e0776e;
  --tint: 63,147,196;       /* the rune blue as bare numbers, for see-through mixes */

  /* The two typefaces, each with fallbacks if the download fails. A serif
     has little feet on its letters (storybook); a sans has none (labels). */
  --serif: "Cormorant Garamond", Georgia, serif;
  --sans: "Archivo", system-ui, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* THE TYPE SCALE — the only letter sizes a page should use. "rem" means
     "times the browser's base size", which is 16 pixels unless the player
     has asked their browser for bigger text (and then everything grows
     with it, which is the point of rem). The floor is 12 pixels: nothing on
     a page is ever smaller than --fs-tiny. */
  --fs-tiny: 0.75rem;       /* 12px — dense data only: table heads, slot numbers */
  --fs-label: 0.8125rem;    /* 13px — the small capitals above things */
  --fs-small: 0.875rem;     /* 14px — secondary text, hints, badges */
  --fs-body: 1rem;          /* 16px — ordinary text, buttons, inputs */
  --fs-read: 1.125rem;      /* 18px — serif reading text (the serif runs small) */
  --fs-h3: 1.25rem;         /* 20px — names inside a card */
  --fs-h2: 1.5rem;          /* 24px — card and section titles */
  /* clamp(smallest, preferred, largest): grows with the screen width (vw is
     1% of it) but never past either end. */
  --fs-h1: clamp(2rem, 6vw, 2.6rem);
  --fs-display: clamp(2.4rem, 9vw, 3.6rem);  /* the front door's title only */

  /* Letter spacing for small capitals. Wide spacing looks grand on a big
     sign and unreadable on a small label, so it is capped here. */
  --track: 0.12em;

  /* Shape and space. */
  --radius: 10px;           /* corner rounding for cards */
  --radius-sm: 8px;         /* corner rounding for controls */
  --tap: 44px;              /* the smallest comfortable finger target */
  --wrap: 60rem;            /* how wide the reading column may grow (960px) */
  --bar-h: 56px;            /* the height of the top bar (section 3) */
}


/* ── 2. THE PAGE ───────────────────────────────────────────────────────── */

/* "*" means every element. border-box makes a stated width include padding
   and border, so "100 wide" really is 100 wide. */
*, *::before, *::after { box-sizing: border-box; }

/* Phones sometimes enlarge text on their own when turned sideways; this
   keeps the size the page chose. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* The canvas: nearly black with a faint gold glow at the top
   (radial-gradient is a soft circle of light that fades out). min-height
   100vh means "at least one screen tall", so a short page is dark to the
   bottom too. */
body {
  /* No gap around the page; at least one screen tall. */
  margin: 0; min-height: 100vh;
  /* Nearly black underneath, with the soft gold glow laid on top. color-mix
     blends 10% gold into "transparent", a faint wash rather than a colour. */
  background: var(--void);
  background-image: radial-gradient(1100px 560px at 50% -10%, color-mix(in srgb, var(--gold) 10%, transparent), transparent);
  /* Light text, in the plain typeface, at the ordinary size. line-height 1.5
     leaves half a line of air between lines, which makes long text easier to
     read. */
  color: var(--parchment);
  font-family: var(--sans); font-size: var(--fs-body); line-height: 1.5;
}

/* The reading column: centred, capped in width, with room at the sides so
   text never touches the edge of a phone. A page that needs more room (a
   wide table) sets --wrap on its own .wrap. (For :where, see the note
   before section 4.) */
:where(.wrap) { max-width: var(--wrap); margin: 0 auto; padding: 24px 16px 80px; }

/* Links: the rune blue, underlined only on hover so a paragraph of them
   stays calm. */
:where(a) { color: var(--rune-bright); text-decoration: none; }
:where(a:hover) { text-decoration: underline; }

/* A visible ring around whatever the keyboard is on (Tab key). Mouse clicks
   don't show it — that is what :focus-visible, rather than :focus, means. */
:where(:focus-visible) { outline: 2px solid var(--gold-bright); outline-offset: 2px; }

/* Both spellings of "hide this", used by page scripts to switch screens.
   !important makes it win over anything else that sets display. */
[hidden], .hidden { display: none !important; }


/* ── 3. THE TOP BAR ────────────────────────────────────────────────────────
   app-auth.js adds a bar across the top of every signed-in page: the Hub
   button on the left, who you are on the right. It used to float over the
   page and sat on top of titles on a phone. Now the page makes room for it:
   app-auth.js marks the document "wg-bar" the moment it loads (before the
   page draws), and the rule below pushes the page down by the bar's height,
   so nothing jumps when the bar appears a moment later. */
html.wg-bar body { padding-top: var(--bar-h); }

/* The bar itself: pinned to the top (position:fixed), full width, and a
   little see-through with a blur behind it (backdrop-filter), so the page
   scrolls under it without clashing. z-index puts it above everything. */
#wg-bar {
  /* Pinned to the top edge, stretched from left to right, drawn above all. */
  position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
  /* As tall as the room the page leaves for it. */
  height: var(--bar-h);
  /* "flex" lines its contents up in a row: centred top-to-bottom, pushed to the
     two ends, with 12px between them. */
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 0 12px;
  /* rgba is a colour plus how solid it is: here the page background, 86%
     solid, so a hint of the page shows through, blurred. */
  background: rgba(6,8,12,0.86);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  /* A hairline along its bottom edge. */
  border-bottom: 1px solid var(--line);
}
/* The Hub button: the one solid gold button on the page, so "home" is
   always the easiest thing to find. When the game is hosting the page, the
   "Back to game" button (#wg-game-btn, #424) takes its place and its look:
   inside the game, the game is home. */
#wg-hub-btn, #wg-game-btn {
  /* Sits in line like text, with its icon and word centred side by side. */
  display: inline-flex; align-items: center; gap: 6px;
  /* Tall enough to tap, with room either side of the word. */
  min-height: 40px; padding: 0 14px;
  font-family: var(--sans); font-size: var(--fs-body); font-weight: 700; letter-spacing: 0.04em;
  /* Dark letters on a gold fill that brightens slightly towards the top
     (linear-gradient blends from one colour to the next, here top to bottom). */
  color: var(--void); text-decoration: none;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  border: 1px solid var(--gold-bright); border-radius: var(--radius-sm);
}
/* Pointing at it: no underline, a touch brighter. */
#wg-hub-btn:hover, #wg-game-btn:hover { text-decoration: none; filter: brightness(1.08); }
/* The game button is a real <button>, so it also needs the hand-shaped
   pointer a link gets for free. */
#wg-game-btn { cursor: pointer; }
/* Who is signed in. margin-left:auto keeps it on the right even when there
   is no Hub button beside it. The ellipsis ("…") trims a very long name. */
#wg-handle-badge {
  /* Never wider than half the bar. */
  margin-left: auto; max-width: 50%;
  /* One line only; whatever doesn't fit is cut off with "…". */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--sans); font-size: var(--fs-small); font-weight: 600;
  color: var(--gold-bright);
}


/* ── WHY THE REST OF THIS FILE IS WRAPPED IN :where( … ) ───────────────────
   When two rules disagree about the same thing, the browser picks the more
   SPECIFIC one: a rule naming a class (".cell") beats one naming only an
   element ("button"), and a rule with extra conditions (":hover") beats one
   without. That is a problem for a shared style: a page's own game tile,
   say a <button class="cell">, would lose its look to the house button rule
   below whenever the house rule happened to be more specific.

   :where( … ) fixes it. Whatever is inside it counts as having NO
   specificity at all, so any rule a page writes for itself wins over the
   house style, every time, without tricks. The house style becomes a
   default, which is exactly what it should be. */


/* ── 4. THE PAGE HEADING ───────────────────────────────────────────────────
   Every page opens the same way, left-aligned:

     SMALL CAPITALS          ← .eyebrow (or h1 .sub): where you are
     The Page Title          ← h1
     A line or two of what   ← p.lede
     this page is for.

   h1 .sub is the small capitals written inside the title, first:
   <h1><span class="sub">Waygate · the bazaar</span>The Bazaar</h1>.
   display:block puts it on its own line over the title. */
:where(.eyebrow, h1 .sub) {
  /* On its own line, with a little space under it... */
  display: block; margin: 0 0 6px;
  font-family: var(--sans); font-size: var(--fs-label); font-weight: 500;
  /* ...spaced-out gold capitals. */
  letter-spacing: var(--track); text-transform: uppercase; color: var(--gold);
}
/* The page title: big gold serif, with lines packed close (line-height 1.1)
   so a two-line title still reads as one. */
:where(h1) {
  margin: 0 0 8px;
  font-family: var(--serif); font-size: var(--fs-h1); font-weight: 600; line-height: 1.1;
  color: var(--gold-bright);
}
/* The introduction under the title: ordinary size, grey, and kept narrow
   (42rem) so a line is never too long to follow. */
:where(.lede) { margin: 0 0 16px; font-size: var(--fs-body); color: var(--ash); max-width: 42rem; }

/* Section headings between cards: small gold capitals. */
:where(h2) {
  margin: 24px 0 10px;
  font-family: var(--sans); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: var(--track); text-transform: uppercase; color: var(--gold);
}


/* ── 5. CARDS ──────────────────────────────────────────────────────────────
   A card is a raised panel holding one job (a form, a list, your standing).
   Its title is the serif, larger and warmer than a section heading. */
:where(.card) {
  /* 14px of space below each card, 16px of room inside it. */
  margin: 0 0 14px; padding: 16px;
  /* A barely-there lighter sheen at the top, over the raised-surface colour. */
  background: linear-gradient(180deg, rgba(255,255,255,0.02), transparent), var(--obsidian);
  /* A hairline edge and rounded corners. */
  border: 1px solid var(--line); border-radius: var(--radius);
}
/* The last thing in a card never adds space below itself: the card's own
   padding is the gap. (Without this, a card ending in an empty message line
   has a blank strip at the bottom.) */
:where(.card > :last-child) { margin-bottom: 0; }
/* A card's own title: the serif at the card-title size, in bright gold,
   undoing the spaced capitals of a section heading. */
:where(.card h2) {
  margin: 0 0 10px;
  font-family: var(--serif); font-size: var(--fs-h2); font-weight: 600;
  letter-spacing: normal; text-transform: none; color: var(--gold-bright);
}
/* A name inside a card: the serif, one step smaller. */
:where(.card h3) { margin: 0 0 6px; font-family: var(--serif); font-size: var(--fs-h3); font-weight: 600; }


/* ── 6. FORMS ──────────────────────────────────────────────────────────────
   A .row lays fields side by side and wraps them onto the next line when
   the screen runs out. A .field stacks a label over its box. max-width 100%
   stops a field with a long option in it from pushing past the edge of a
   phone. */
:where(.row) { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
:where(.field) { display: flex; flex-direction: column; gap: 4px; max-width: 100%; }
/* Field labels: small grey capitals, slightly spaced. */
:where(label) {
  font-size: var(--fs-label); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ash);
}

/* Text boxes and drop-downs. 16px text matters on a phone: an iPhone zooms
   the whole page into any box whose text is smaller, and does not zoom back. */
:where(input, select, textarea, .nameinput) {
  /* Never wider than the screen, at least a finger tall, room inside. */
  max-width: 100%; min-height: var(--tap); padding: 8px 12px;
  font-family: var(--sans); font-size: var(--fs-body);
  /* Light text on the sunken-surface colour, with a hairline rounded edge. */
  color: var(--parchment); background: var(--well);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
/* Tick boxes and radio dots keep their natural small size. */
:where(input[type="checkbox"], input[type="radio"]) { min-height: 0; padding: 0; }
:where(textarea) { line-height: 1.45; }
/* The box being typed in gets a gold edge instead of the browser's ring. */
:where(input:focus, select:focus, textarea:focus, .nameinput:focus) { outline: none; border-color: var(--gold); }
/* The "type your handle" box used by the older pages. */
:where(.nameinput) { min-width: 14rem; }
:where(.namebox) { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

/* Buttons. Every page used two looks: the main gold action, and a quiet
   "ghost" for secondary things like Refresh. The class names differed
   (.act / .ghostbtn / .ghost); all of them are styled here the same.
   A link can wear the look too (<a class="act">); inline-flex gives it the
   same height and centring as a real button. Only buttons and links take
   the look from a class: a <div class="act"> is left alone, because some
   pages use that name for the row that HOLDS a card's buttons. */
:where(button, a.act, a.ghost, a.ghostbtn, .ghostbtn) {
  /* Contents centred in both directions, side by side. */
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  /* At least a finger tall. */
  min-height: var(--tap); padding: 8px 16px;
  font-family: var(--sans); font-size: var(--fs-body); font-weight: 600; line-height: 1.2;
  /* Bright gold words on a faint gold wash (14% gold), with a gold edge. */
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 14%, transparent);
  border: 1px solid var(--gold); border-radius: var(--radius-sm);
  /* A hand pointer, and a 0.15-second fade when the wash changes. */
  text-decoration: none; cursor: pointer; transition: background 0.15s;
}
/* Pointing at an enabled button doubles the wash to 28%. */
:where(button:hover:not(:disabled), a.act:hover) { background: color-mix(in srgb, var(--gold) 28%, transparent); text-decoration: none; }
/* The quiet look: grey words, no wash, a hairline edge... */
:where(button.ghost, a.ghost, .ghostbtn) { color: var(--ash); background: transparent; border-color: var(--line); }
/* ...that lights up a little when pointed at. */
:where(button.ghost:hover:not(:disabled), a.ghost:hover, .ghostbtn:hover:not(:disabled)) { color: var(--parchment); background: rgba(255,255,255,0.04); text-decoration: none; }
/* A button that can't be pressed right now: half-faded, no hand pointer. */
:where(button:disabled) { opacity: 0.5; cursor: default; }


/* ── 7. SMALL THINGS ───────────────────────────────────────────────────── */

/* A chip or pill: a small rounded tag of status text. If a long one has to
   wrap onto two lines, it stays inside the screen. */
:where(.chip, .pill, .badge) {
  /* In line with text, never wider than the screen. */
  display: inline-block; max-width: 100%; padding: 3px 10px;
  font-family: var(--sans); font-size: var(--fs-small); letter-spacing: 0.04em;
  /* A border-radius far bigger than the chip makes fully round ends. */
  color: var(--ash); border: 1px solid var(--line); border-radius: 999px;
}
/* A .bar is a row of chips or buttons. Pages often fill one in later from
   a script; until then (":empty") it takes no room, so it doesn't leave a
   blank gap under the heading. */
:where(.bar) { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 14px; }
:where(.bar:empty) { display: none; }

/* Messages: a quiet helper line, an empty list, and an apology when
   something went wrong (#msg and #apology are the ids pages use for it). */
:where(.hint, .muted, .empty) { font-size: var(--fs-small); color: var(--ash); }
:where(.empty) { font-style: italic; }
:where(.apology, #apology, #msg) { min-height: 1.4em; margin: 6px 0 14px; font-style: italic; color: var(--ember); }

/* Tables: data in rows. The wrapper lets a wide table scroll sideways by
   itself instead of pushing the whole page off the side of a phone. */
:where(.tablewrap) { overflow-x: auto; }
/* Tables: no doubled borders, full width, slightly smaller text. */
:where(table) { border-collapse: collapse; width: 100%; font-size: var(--fs-small); }
/* Column heads: left-aligned, tiny grey capitals over a hairline. */
:where(th) {
  text-align: left; padding: 8px; border-bottom: 1px solid var(--line);
  font-size: var(--fs-tiny); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ash); font-weight: 500;
}
/* Cells: room inside, a hairline under each row, text starting at the top. */
:where(td) { padding: 8px; border-bottom: 1px solid var(--line); vertical-align: top; }

/* The row of links at the foot of a page. Each link is tall enough to tap. */
:where(.backlink) { display: flex; flex-wrap: wrap; gap: 0 20px; margin-top: 32px; }
/* Each footer link: tap-tall, in small spaced grey capitals. */
:where(.backlink a) {
  display: inline-flex; align-items: center; min-height: var(--tap);
  font-family: var(--sans); font-size: var(--fs-label); letter-spacing: var(--track);
  text-transform: uppercase; color: var(--ash);
}
:where(.backlink a:hover) { color: var(--rune-bright); text-decoration: none; }


/* ── 8. THE PICKER ─────────────────────────────────────────────────────────
   pick.js draws a list of your own things to choose from (which gear to
   sell, which ticket to spend, which creatures to send), in place of a box
   where you used to type an id. Each row is a button: the name on top, the
   details in grey underneath. The chosen row is outlined in gold. The list
   scrolls by itself once it is long, so it never pushes the page away. */
/* The whole picker: a column, never wider than 32rem. */
:where(.pick) { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 32rem; }
/* The search box, once there are six or more rows. */
:where(.pick-find) { width: 100%; }
/* The list of rows: a column that scrolls once it passes 18rem tall. */
:where(.pick-list) {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 18rem; overflow-y: auto; padding: 2px;
}
/* One row: a full-width, finger-tall button with its words stacked and
   left-aligned, on the sunken-surface colour. */
:where(.pick-row) {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px;
  width: 100%; min-height: var(--tap); padding: 8px 12px; text-align: left;
  font-weight: 500; color: var(--parchment);
  background: var(--well); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
/* Pointing at a row lifts it slightly. */
:where(.pick-row:hover:not(:disabled)) { background: rgba(255,255,255,0.04); border-color: var(--ash); }
/* A chosen row: a gold edge and a gold-tinted fill. aria-selected is the
   label pick.js puts on a chosen row, which screen readers also announce. */
:where(.pick-row[aria-selected="true"]) {
  border-color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, var(--well));
}
/* The row's name at the ordinary size; its details smaller and grey. */
:where(.pick-name) { font-size: var(--fs-body); }
:where(.pick-detail) { font-size: var(--fs-small); font-weight: 400; color: var(--ash); }
/* The line under the list that says what is chosen (or why nothing is). */
:where(.pick-status) { margin: 0; min-height: 1.4em; }
