/* Unnecessary Obstacles: the hub, printed on the paper (ADR 0036): the
   pencil puzzles' warm cream and graphite, Gloock for titles and Figtree
   for the rest, from the house's one paper palette
   (games/house/paper.css, loaded before this). The game boxes are cards on
   the paper, each with its game's art on its tile color. Always paper, as
   the puzzles are, whatever the reader's dark-mode setting. See
   docs/design-system.md, "The hub". The hub is only a shelf: each game
   brings its own look once you open it. */
:root {
  /* the hub's names on the paper */
  --card: var(--paper-2);
  --ink-soft: var(--soft);
  --edge: 1px solid var(--paper-edge);       /* a card's edge, a hairline rule */
  --field-edge: 1px solid var(--line);       /* a field's or a chip's edge */
  --radius: 12px;                            /* a card */
  --btn-radius: 8px;                         /* a button, a field, a tile's mark */
  --font: var(--ui);
  /* the tiles: board-game primaries, one per game */
  --red: #e63b2e;
  --blue: #2b59c3;
  --yellow: #f5c518;
  --green: #2e8b57;
  /* The house rules' tokens (docs/design-system.md), the same small set
     every UO game declares: five type roles, five spaces, one way to show
     a pick (drawn in currentColor, so it takes the ink it sits on). */
  --t-display: 44px;
  --t-heading: 20px;
  --t-body: 16px;
  --t-label: 16px;
  --t-note: 14px;
  --s1: 4px; --s2: 8px; --s3: 16px; --s4: 24px; --s5: 40px;
  --pick-tint: color-mix(in srgb, currentColor 9%, transparent);
  --pick-ring: inset 0 0 0 2px currentColor;
  --pick-weight: 700;
  /* the house kit's names for them (its sheets and toasts: Feedback, the
     rating's "?"), on the paper as the puzzle kit has them */
  --house-surface: var(--paper-2);
  --house-ink: var(--ink);
  --house-soft: var(--soft);
  --house-edge: var(--edge);
  --house-line: var(--paper-edge);
  --house-field-edge: var(--field-edge);
  --house-radius: 14px;
  --house-btn-radius: var(--btn-radius);
  --house-font: var(--ui);
  --house-display: var(--display);
  --house-display-weight: 400;
  --house-focus: var(--ink);
  --house-scrim: rgba(34, 30, 20, .5);
  --house-shadow: 0 28px 70px rgba(34, 30, 20, .45);
  --house-toast-edge: var(--edge);
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body { background: var(--paper) var(--paper-grain); color: var(--ink); font: var(--t-body)/1.5 var(--font); -webkit-font-smoothing: antialiased; }
a { color: inherit; }
.wrap { max-width: 1040px; margin: 0 auto; padding: 0 max(20px, env(safe-area-inset-right, 0px)) 0 max(20px, env(safe-area-inset-left, 0px)); }

/* header: the wordmark and a single tag, on a hairline */
.top .wrap { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding-top: 22px; padding-bottom: 14px; border-bottom: var(--edge); }
.brand-h { margin: 0; font-size: inherit; line-height: inherit; font-weight: inherit; }
.brand { font: 400 24px/1.2 var(--display); letter-spacing: -.005em; text-decoration: none; }
.chip { font-size: 13px; font-weight: 600; color: var(--ink-soft); border: var(--field-edge); border-radius: 99px; padding: 2px 12px; text-decoration: none; }

main { padding: 28px 0 64px; }
/* the one line on the shelf: Suits's definition, which gives the place its name */
.epigraph { margin: 4px 0 30px; max-width: 34em; }
.epigraph blockquote { margin: 0; font: 400 26px/1.3 var(--display); letter-spacing: -.005em; }
.epigraph figcaption { margin-top: 8px; font-size: 14px; color: var(--ink-soft); }

/* the shelf: one card per game, its art on its tile color over its name */
.shelf { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px; }
.box {
  display: flex; flex-direction: column; text-decoration: none; background: var(--card); border: var(--edge); border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--card-shadow); transition: transform .15s ease, box-shadow .15s ease;
}
.box:hover, .box:focus-visible { transform: translateY(-3px); box-shadow: var(--card-shadow-up); }
.box:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.box .art { aspect-ratio: 16 / 10; background: var(--tile, var(--red)); border-bottom: var(--edge); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.box .art svg { width: 100%; height: calc(100% + 1px); display: block; }
.box .label { padding: 10px 12px 12px; }
.box .label b { display: block; font-size: 17px; font-weight: 700; }
.box .label span { display: block; font-size: var(--t-note); color: var(--ink-soft); }
/* how many play, and a daily: furniture, like a badge or a count */
.box .label small { display: block; margin-top: 6px; font-size: 13px; font-weight: 600; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.box.soon { border: 1.5px dashed var(--line); background: transparent; box-shadow: none; pointer-events: none; }
.box.soon .art { background: transparent; border-bottom: 1.5px dashed var(--line); color: var(--ink-soft); font-size: 28px; }

/* the hub's one way to the dailies (docs/adr/0034): a wide card above the
   shelf, lifting like the games' boxes, its mark on the yellow tile */
.dailies-link {
  display: flex; align-items: center; gap: var(--s3); margin: 0 0 var(--s4); padding: 12px 16px 12px 12px; text-decoration: none;
  background: var(--card); border: var(--edge); border-radius: var(--radius); box-shadow: var(--card-shadow); transition: transform .15s ease, box-shadow .15s ease;
}
.dailies-link:hover, .dailies-link:focus-visible { transform: translateY(-3px); box-shadow: var(--card-shadow-up); }
.dailies-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.dailies-mark { flex: none; display: grid; place-items: center; width: 56px; height: 56px; border-radius: var(--btn-radius); background: var(--yellow); color: var(--ink); }
.dailies-mark svg { width: 34px; height: 34px; }
/* A streak at stake (hub-dailies.js): a dot on the mark, and the line says so. */
.dailies-link.at-stake .dailies-mark { position: relative; }
.dailies-link.at-stake .dailies-mark::after { content: ''; position: absolute; top: -4px; right: -4px; width: 14px; height: 14px; border-radius: 50%; background: var(--red, var(--ink)); box-shadow: 0 0 0 3px var(--card, var(--paper)); }
.dailies-words { flex: 1; min-width: 0; }
.dailies-words b { display: block; font-size: 17px; }
.dailies-words span { display: block; font-size: var(--t-note); color: var(--ink-soft); }
.dailies-go { flex: none; font-size: 22px; font-weight: 700; }

/* a shelf big enough for sections and filters (docs/adr/0020). Everything
   here is in the page as sent, so nothing moves when the script arrives. */
.shelf-wrap [hidden] { display: none; }
.family + .family { margin-top: var(--s4); }
.family h2 { margin: 0 0 var(--s3); padding-bottom: var(--s2); font-size: var(--t-heading); line-height: 1.3; border-bottom: var(--edge); }
/* the chips: choosing isn't doing (house rule 3), so a pick is a tint, an
   inner ring and bold, on the soft line, never the primary fill */
.filters { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s2); }
.filters ul { display: contents; list-style: none; margin: 0; padding: 0; }
.f-chip { display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px; font-size: var(--t-note); font-weight: 500; text-decoration: none; background: color-mix(in srgb, var(--paper-2) 60%, transparent); border: var(--field-edge); border-radius: 99px; }
.f-chip:hover { border-color: var(--ink); }
.f-chip[aria-current] { background: var(--pick-tint); box-shadow: var(--pick-ring); border-color: transparent; font-weight: var(--pick-weight); }
/* the bold width is held by every chip, so picking one never moves the next */
.f-chip span::after { content: attr(data-text); display: block; height: 0; overflow: hidden; visibility: hidden; font-weight: var(--pick-weight); }
.f-chip:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 99px; }
.shelf-status { margin: 0 0 var(--s3); min-height: 1.5em; font-size: var(--t-note); color: var(--ink-soft); }
.shelf-status a { color: var(--ink); text-underline-offset: 3px; }

/* the hub's one account line, under the shelf: plain words, the same spot
   signed in or out (docs/adr/0011) */
.account-line { margin: 30px 0 0; font-size: var(--t-note); line-height: 1.5; color: var(--ink-soft); }
.account-line a, .account-line .links { white-space: nowrap; }
.account-line b { color: var(--ink); font-weight: 600; }
.account-line a, .rp-small a, .mine a, .account-delete a { color: var(--ink); text-underline-offset: 3px; }
:is(.account-line, .rp-small, .mine, .account-delete) a:hover { text-decoration-thickness: 2px; }
:is(a, button, input):focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 2px; }

/* the foot (house rule 10): the way back at the left, the copyright at the right */
footer .wrap { display: flex; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; border-top: var(--edge); padding-top: 12px; padding-bottom: max(28px, calc(env(safe-area-inset-bottom, 0px) + 12px)); font-size: 13px; color: var(--ink-soft); }
footer .wrap > :last-child { margin-left: auto; }
footer a { color: var(--ink); font-weight: 600; font-size: var(--t-note); text-decoration: none; }
footer a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* titles in Gloock, as the puzzles set them; staff pages (stats) share the look */
h1 { font: 400 var(--t-display)/1.1 var(--display); letter-spacing: -.005em; margin: 0 0 10px; }
h2 { font-size: var(--t-heading); margin: 32px 0 12px; }
.lead { color: var(--ink-soft); max-width: 44em; }
.kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.kpi { border: var(--edge); border-radius: var(--radius); padding: 12px 14px; background: var(--card); box-shadow: var(--card-shadow); }
.kpi b { display: block; font-size: 28px; }
.kpi span { color: var(--ink-soft); font-size: var(--t-note); }
table.ranks { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
table.ranks th { text-align: left; font-size: 13px; color: var(--ink-soft); padding: 8px; border-bottom: 1px solid var(--line-bold); }
table.ranks td { padding: 8px; border-bottom: var(--edge); }
table.ranks .num { text-align: right; }
.bar { height: 8px; background: var(--yellow); border-radius: 2px; min-width: 2px; }

/* account pages (/account/…): the hub's look for its forms, shared with the
   games' account templates, so they keep those class names (rp-card, rp-form,
   rp-small) */
.kicker { font-size: 12px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 8px; }
/* The owner's Analytics (staff only, static/js/analytics.js): charts on
   cards. Signed-in players in the tiles' blue, guests in amber (checked for
   colorblind readers against the card; the amber is under 3:1, so every
   chart has its key, a tooltip and a table). Words stay in the inks. */
.kpis + .an-charts { margin-top: 12px; }
.an-charts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.an-card { position: relative; border: var(--edge); border-radius: var(--radius); padding: 14px 16px; background: var(--card); box-shadow: var(--card-shadow); min-width: 0; }
.an-card.an-wide { grid-column: 1 / -1; }
.an-card h3 { font-size: var(--t-label); margin: 0 0 4px; }
.an-note { color: var(--ink-soft); font-size: var(--t-note); margin: 0 0 8px; }
.an-key { display: flex; gap: var(--s3); margin: 0 0 8px; font-size: var(--t-note); color: var(--ink-soft); }
.an-key i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 6px; vertical-align: -1px; }
.an-chart { position: relative; }
.an-plot { width: 100%; }
.an-plot svg { display: block; overflow: visible; }
.an-mark.acct, .an-key .acct, .an-mark.one { fill: #2b59c3; background: #2b59c3; }
.an-mark.guest, .an-key .guest { fill: #e0952b; background: #e0952b; }
.an-hit { fill: transparent; }
.an-grid { stroke: var(--paper-edge); stroke-width: 1; }
.an-base { stroke: var(--line); stroke-width: 1; }
.an-axis { fill: var(--ink-soft); font-size: 11px; font-variant-numeric: tabular-nums; }
.an-value { fill: var(--ink); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.an-tip { position: absolute; top: 0; left: var(--x, 50%); transform: translate(-50%, -110%); background: var(--ink); color: var(--paper-2); font-size: 12px; padding: 4px 8px; border-radius: 6px; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity .12s; }
.an-chart.reading .an-tip { opacity: 1; }
.an-scroll { overflow-x: auto; }
.an-players td { white-space: nowrap; }
.an-spark { display: inline-block; vertical-align: middle; line-height: 0; }
.an-tag { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); }
@media (max-width: 720px) { .an-charts { grid-template-columns: 1fr; } }
/* The footer's "Analytics", for staff only: as quiet as Feedback beside it. */
footer .admin-link { font-weight: 400; color: var(--ink-soft); }
.wrap > h1 + .lead { font-size: 17px; margin: 0 0 26px; }
h1 + .rp-card { margin-top: 24px; }
.messages { list-style: none; margin: 0 0 22px; padding: 0; }
.messages li { border: var(--edge); border-left: 3px solid var(--good); border-radius: var(--btn-radius); background: var(--card); padding: 9px 14px; max-width: 460px; }
.rp-card { background: var(--card); border: var(--edge); border-radius: var(--radius); box-shadow: var(--card-shadow); padding: 22px 24px; max-width: 460px; }
.rp-form p { margin: 0 0 16px; }
.rp-form p:last-child { margin-bottom: 0; }
.rp-form label { display: block; font-weight: 700; font-size: 14px; margin-bottom: 6px; }
.rp-form input:not([type=hidden]) {
  width: 100%; min-height: 44px; padding: 9px 12px; font: 16px var(--font); color: var(--ink);
  background: var(--paper-2); border: var(--field-edge); border-radius: var(--btn-radius);
}
.rp-form input:not([type=hidden]):focus { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); outline: none; }
.rp-form .helptext { display: block; color: var(--ink-soft); font-size: var(--t-note); margin-top: 5px; }
.rp-form .helptext ul { margin: 4px 0 0; padding-left: 18px; }
ul.errorlist { list-style: none; padding: 0; margin: 6px 0 0; color: var(--bad); font-size: var(--t-note); font-weight: 700; }
/* a form-wide error (wrong password) sits above the fields, not on them */
.rp-form > ul.errorlist { margin: 0 0 14px; }
.rp-small { color: var(--ink-soft); font-size: var(--t-note); }
/* three button weights (house rule 2), drawn as the puzzles draw them:
   outlined graphite; the one filled, graphite with a lip that presses down
   (the hub has no accent of its own: each game brings its own); and words */
.btn {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 8px 18px;
  font: 700 15px/1.1 var(--font); color: var(--ink); background: transparent; border: 2px solid var(--line-bold); border-radius: var(--btn-radius);
  text-decoration: none; cursor: pointer; transition: background-color .12s ease, transform .12s ease, box-shadow .12s ease;
}
@media (hover: hover) { .btn:hover { background: color-mix(in srgb, var(--ink) 7%, transparent); } }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.btn.primary { background: var(--ink); border-color: var(--ink); color: var(--paper-2); box-shadow: 0 2px 0 #000; }
@media (hover: hover) { .btn.primary:hover { background: color-mix(in srgb, var(--ink) 86%, #fff); } }
.btn.primary:active { box-shadow: none; transform: translateY(2px); }
.btn.primary:focus-visible { outline-offset: 3px; }
.btn.danger { color: var(--bad); border-color: var(--bad); }
@media (hover: hover) { .btn.danger:hover { background: color-mix(in srgb, var(--bad) 8%, transparent); } }
/* the third weight: words, underlined (house rule 2) */
.btn.quiet { border-color: transparent; text-decoration: underline; text-underline-offset: 4px; padding-left: 10px; padding-right: 10px; font-weight: 600; }
@media (hover: hover) { .btn.quiet:hover { background: none; text-decoration-thickness: 2px; } }

/* your account: what each game keeps for you, beside your settings */
.account { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 40px; align-items: start; }
.account h2 { font-size: var(--t-note); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 12px; }
.account .rp-card { max-width: none; }
.mine { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }
.mine li { display: grid; grid-template-columns: 168px minmax(0, 1fr); background: var(--card); border: var(--edge); border-radius: var(--radius); box-shadow: var(--card-shadow); overflow: hidden; }
.mine-art { display: block; background: var(--tile); border-right: var(--edge); min-height: 105px; }
.mine-art svg { width: 100%; height: calc(100% + 1px); display: block; }
.mine-text { padding: 12px 16px 14px; min-width: 0; }
.mine h3 { font-size: 18px; margin: 0 0 4px; }
.mine h3 a { text-decoration: none; }
.mine h3 a:hover { text-decoration: underline; }
.mine p { margin: 0; font-size: 15px; color: var(--ink-soft); }
.mine p.mine-links { margin-top: 8px; color: var(--ink-soft); }
/* your ratings: one row a game, strongest first, a bar leaning left or
   right of the 1500 everyone starts at, in the game's tile color */
.ratings { margin-bottom: 30px; }
.ratings-list { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 10px; }
.ratings-list li { display: grid; grid-template-columns: minmax(0, 11em) minmax(60px, 1fr) 4.5em; align-items: center; gap: 12px; }
.ratings-list a { color: var(--ink); text-underline-offset: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ratings-list a:hover { text-decoration-thickness: 2px; }
.ratings-list b { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.ratings-list b.provisional { color: var(--ink-soft); font-weight: 600; }
.ratings-bar { position: relative; height: 12px; border-radius: 99px; background: color-mix(in srgb, var(--ink) 8%, transparent); }
.ratings-bar::before { content: ""; position: absolute; left: 50%; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--ink-soft); }
.ratings-bar span { position: absolute; top: 0; bottom: 0; min-width: 4px; border-radius: 99px; background: var(--tile); border: 1px solid var(--ink); }
.ratings .rp-small { margin: 0; }
.account-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0 0; }
.account-actions form { display: contents; }
.account-delete { margin-top: 30px; padding-top: 16px; border-top: var(--edge); }
.account-delete h3 { font-size: 15px; margin: 0 0 4px; }
/* the way to the technical guide, quiet, under it all (docs/adr/0035) */
.account-guide { margin: var(--s5) 0 0; }
.account-guide a { color: var(--ink); text-underline-offset: 3px; }
.account-delete p { margin: 0 0 6px; font-size: 15px; }

@media (prefers-reduced-motion: reduce) {
  .box, .btn, .dailies-link { transition: none; }
}

@media (max-width: 860px) {
  .account { grid-template-columns: 1fr; gap: 30px; }
  /* signed out the line takes two lines here; signed in keeps the same room */
  .account-line { min-height: 3em; }
}

/* (a title in Gloock steps down on a phone, as the puzzles' do) */
@media (max-width: 640px) {
  h1 { font-size: 32px; }
}

@media (max-width: 560px) {
  .mine li { grid-template-columns: 112px minmax(0, 1fr); }
  .ratings-list li { grid-template-columns: minmax(0, 1fr) 32% 4.2em; gap: 10px; }
  .ratings-list a { white-space: normal; }
  /* the art keeps its 16:10, centered beside the text; the rule runs down the text's side */
  .mine-art { aspect-ratio: 16 / 10; min-height: 0; align-self: center; border-right: 0; }
  .mine-art svg { height: 100%; }
  .mine-text { border-left: var(--edge); }
  .rp-card { padding: 18px; }
  .shelf { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .box .label b { font-size: 15px; }
  .filters { gap: 6px; }
  .f-chip { padding: 0 12px; min-height: 36px; }
  .epigraph blockquote { font-size: 22px; }
  .brand { font-size: 21px; }
  table.ranks .hide-sm { display: none; }
}
/* A finger's reach on a touch screen (docs/design-language.md, "Fine
   details"): the filters are 44px tall, and the wordmark is pressed
   anywhere in the 44px round its line, without moving it. */
@media (pointer: coarse) {
  .f-chip { min-height: 44px; }
  .brand { display: inline-block; padding-block: 10px; margin-block: -10px; }
  /* the foot's way back, whichever page wears it */
  footer .wrap > a { display: inline-flex; align-items: center; min-height: 44px; margin-block: -12px; }
  /* (and the technical guide's link beside the copyright, docs/adr/0035) */
  footer .guide-link, footer .admin-link { display: inline-flex; align-items: center; min-height: 44px; margin-block: -12px; }
}

/* a page that isn't here, or a server error (templates/404.html, 500.html):
   a short screen with the way back (docs/design-language.md, "Loading,
   empty, error") */
.lost { padding: var(--s4) 0 var(--s5); }
.lost .lead { margin: 0 0 var(--s4); }
.lost-ways { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); margin: 0; }
