:root {
  /* Palette derived from the Qpio mark (D-057). Hues 180-210deg, navy -> cyan. */
  --bg: #071722;          /* deep navy-black, the mark's darkest value */
  --bg2: #0B2233;
  --card: #0F2C3F;
  --card2: #164056;
  --ink: #EAF4F8;
  --muted: #8FB0C0;
  --line: #1E4A63;
  --brand: #26BAD8;       /* the mark's brightest cyan - the single accent */
  --brand2: #1E95AD;      /* mid teal, for depth only - not a second accent */
  --accent: #26BAD8;
  --good: #3FBF9A;
  --bad: #E4695F;
  --radius: 16px;
  --shadow: 0 10px 40px rgba(0,0,0,.5);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font);
  color: var(--ink);
  background:
    radial-gradient(1200px 600px at 80% -10%, #0E3B52 0%, transparent 60%),
    radial-gradient(900px 500px at -10% 20%, #0A2C3E 0%, transparent 55%),
    var(--bg);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: 720px; margin: 0 auto; padding: 20px 18px 80px; }

/* Header */
.top { display: flex; align-items: center; justify-content: space-between; margin: 8px 0 22px; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 22px; letter-spacing: .3px; }
.logo .mark { font-size: 26px; }
.logo .name { color: var(--ink); letter-spacing: -.01em; }
.tag { color: var(--muted); font-size: 12.5px; font-weight: 500; }
.streakchip { display: flex; align-items: center; gap: 6px; background: var(--card); border: 1px solid var(--line); padding: 8px 12px; border-radius: 999px; font-weight: 700; font-size: 14px; }

/* Home cards */
.grid { display: grid; gap: 14px; }
/* Grid and flex children default to min-width:auto, so a child that cannot
   shrink below its content — a horizontal shelf of eight 190px cards — widens
   the whole column and every sibling with it. Measured: a 229px column became
   1019px and the page scrolled sideways. min-width:0 lets the shelf's own
   overflow-x do its job instead (2026-08-08). */
.grid > *, .row > * { min-width: 0; }
.rack-row, .keep-row, .topic-body, .dcard-body { min-width: 0; }
.card {
  background: linear-gradient(180deg, var(--card), var(--bg2));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow);
}
.hero { position: relative; overflow: hidden; }
.hero::after { content: ""; position: absolute; inset: 0; background: radial-gradient(400px 200px at 90% 0%, rgba(38,186,216,.12), transparent 70%); pointer-events: none; }
.hero h1 { margin: 4px 0 6px; font-size: 24px; }
.hero p { margin: 0 0 16px; color: var(--muted); font-size: 14.5px; line-height: 1.5; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.mode { flex: 1 1 220px; cursor: pointer; text-align: left; transition: transform .12s ease, border-color .12s ease; }
.mode:hover { transform: translateY(-2px); border-color: var(--accent); }
.mode h3 { margin: 8px 0 4px; font-size: 17px; }
.mode p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }
.mode .emoji { font-size: 26px; }
.pill { display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; padding: 3px 9px; border-radius: 999px; }
.pill.free { background: rgba(79,214,163,.15); color: var(--good); border: 1px solid rgba(79,214,163,.3); }
.pill.kids { background: rgba(255,209,102,.15); color: var(--brand); border: 1px solid rgba(255,209,102,.35); margin-left: 6px; }

/* Buttons */
.btn {
  appearance: none; border: none; cursor: pointer; font-family: var(--font);
  font-weight: 700; font-size: 15px; color: #17162b;
  background: var(--brand);
  padding: 13px 20px; border-radius: 12px; transition: filter .12s ease, transform .12s ease;
}
.btn:hover { filter: brightness(1.06); transform: translateY(-1px); }
.btn.ghost { background: transparent; color: var(--ink); border: 1px solid var(--line); }
.btn.ghost:hover { border-color: var(--accent); }
.btn.block { width: 100%; }
.btn:disabled { opacity: .5; cursor: default; transform: none; }
.btnrow { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }

/* Category chips */
.cats { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.chip { cursor: pointer; background: var(--card2); border: 1px solid var(--line); color: var(--ink); padding: 8px 13px; border-radius: 999px; font-size: 13px; font-weight: 600; transition: all .12s ease; }
.chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Quiz */
.quizhead { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.progress { flex: 1; height: 8px; background: var(--card2); border-radius: 999px; overflow: hidden; margin: 0 14px; }
.progress > i { display: block; height: 100%; background: var(--brand); width: 0; transition: width .3s ease; }
.qmeta { color: var(--muted); font-size: 13px; font-weight: 600; white-space: nowrap; }
.qcat { display: inline-block; font-size: 12px; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .6px; margin-bottom: 6px; }
.qtext { font-size: 21px; font-weight: 700; line-height: 1.35; margin: 2px 0 18px; }
.opts { display: grid; gap: 11px; }
.opt {
  text-align: left; cursor: pointer; font-family: var(--font); font-size: 15.5px; font-weight: 600;
  color: var(--ink); background: var(--card2); border: 1.5px solid var(--line);
  padding: 15px 16px; border-radius: 12px; transition: all .12s ease; display: flex; align-items: center; gap: 12px;
}
.opt:hover:not(:disabled) { border-color: var(--accent); }
.opt .key { width: 26px; height: 26px; flex: none; display: grid; place-items: center; border-radius: 7px; background: var(--bg2); border: 1px solid var(--line); font-size: 13px; font-weight: 800; }
.opt.correct { border-color: var(--good); background: rgba(79,214,163,.14); }
.opt.correct .key { background: var(--good); color: #10321f; border-color: var(--good); }
.opt.wrong { border-color: var(--bad); background: rgba(255,107,129,.12); }
.opt.wrong .key { background: var(--bad); color: #3a0d16; border-color: var(--bad); }
.opt:disabled { cursor: default; }

/* Fact reveal */
/* Entrance animation runs automatically on insertion — visibility never
   depends on requestAnimationFrame (which pauses in backgrounded tabs). */
/* Animate only a subtle slide — never opacity — so the content is readable
   even if the animation is paused (backgrounded tab) at its first frame. */
@keyframes curioReveal { from { transform: translateY(6px); } to { transform: none; } }
.fact { margin-top: 16px; padding: 15px 16px; border-radius: 12px; background: rgba(124,108,255,.12); border: 1px solid rgba(124,108,255,.35); font-size: 14.5px; line-height: 1.5; opacity: 1; animation: curioReveal .25s ease; }
.fact.show { opacity: 1; transform: none; }
.fact b { color: var(--brand); }
/* The verdict is a small mark, not the headline. Charter VAL-13: "Correct!"
   in bold at the front of the sentence is scorekeeping, and it closes the gap
   the surprise needs. The fact leads; the tick sits beside it. */
.verdict {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: baseline;
  margin-right: 8px; padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase;
}
.verdict.ok { color: var(--good); background: rgba(79,214,163,.14); border: 1px solid rgba(79,214,163,.42); }
.verdict.no { color: var(--bad);  background: rgba(255,107,129,.12); border: 1px solid rgba(255,107,129,.42); }
/* The answer clock — the metric that replaced Easy/Medium/Hard. Quiet, factual. */
.speedchip { font-size: 11px; font-weight: 700; opacity: .75; margin-left: 6px; }
.timer { font-variant-numeric: tabular-nums; font-weight: 800; }
.timer.low { color: var(--bad); }

/* Results */
.result { text-align: center; }
.scorebig { font-size: 56px; font-weight: 900; color: var(--brand); line-height: 1.1; }
.result h2 { margin: 6px 0 2px; }
.result .sub { color: var(--muted); margin-bottom: 18px; }
.sharebox { background: var(--bg2); border: 1px dashed var(--line); border-radius: 12px; padding: 14px; font-size: 20px; letter-spacing: 3px; margin: 6px 0 4px; }
.mini { color: var(--muted); font-size: 12.5px; margin-top: 6px; }

/* Leaderboard */
.lb { list-style: none; margin: 8px 0 0; padding: 0; }
.lb li { display: flex; align-items: center; justify-content: space-between; padding: 11px 4px; border-bottom: 1px solid var(--line); font-size: 14.5px; }
.lb li:last-child { border-bottom: none; }
.lb .rank { color: var(--muted); font-weight: 800; width: 28px; }
.lb .who { flex: 1; font-weight: 600; }
.lb .pts { font-weight: 800; color: var(--brand); }
.empty { color: var(--muted); font-size: 14px; text-align: center; padding: 16px; }

.section-title { font-size: 13px; text-transform: uppercase; letter-spacing: .7px; color: var(--muted); font-weight: 700; margin: 26px 4px 2px; }
.footer { text-align: center; color: var(--muted); font-size: 12px; margin-top: 34px; line-height: 1.7; }
.footer a { color: var(--brand2); text-decoration: none; }
.hidden { display: none !important; }
.center { text-align: center; }

/* Memory Vault */
.vaultcard { border-color: rgba(255,209,102,.4); }
.vaultcard h3 { margin: 0 0 4px; font-size: 17px; }
.vaultcard p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.vaultcard.quiet { opacity: .85; }
.vaultrow { display: flex; align-items: center; gap: 14px; }
.vaultrow > div { flex: 1; }

/* Brain Map */
.bm-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; }
.bm-cat { width: 118px; flex: none; font-size: 13.5px; font-weight: 600; }
.bm-bar { flex: 1; height: 10px; background: var(--card2); border-radius: 999px; overflow: hidden; }
.bm-bar > i { display: block; height: 100%; border-radius: 999px; background: var(--brand); transition: width .4s ease; }
.bm-lv { width: 110px; flex: none; text-align: right; font-size: 12px; color: var(--muted); font-weight: 700; }

/* Comfort panel */
.cf-group { padding: 13px 0; border-bottom: 1px solid var(--line); }
.cf-group:last-of-type { border-bottom: none; }
.cf-title { font-weight: 800; font-size: 15px; }
.cf-group .cats { margin-top: 8px; }

/* Source links + rabbit holes */
.srclink { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px;
  color: var(--brand2); text-decoration: none; font-size: 14px; font-weight: 700;
  background: rgba(255,143,163,.10); border: 1px solid rgba(255,143,163,.40);
  padding: 8px 13px; border-radius: 999px; white-space: nowrap; }
.srclink:hover { background: rgba(255,143,163,.18); border-color: var(--brand2); }
.fact-deeper { margin-top: 10px; padding: 12px 14px; border-radius: 10px; background: rgba(255,209,102,.10); border: 1px solid rgba(255,209,102,.3); font-size: 14px; line-height: 1.5; opacity: 1; animation: curioReveal .25s ease; }
.fact-deeper.show { opacity: 1; transform: none; }

/* After an answer, the options you did not pick are removed — they carried
   information only while the choice was open, and every one of them competes
   with the fact for attention (CEO, 2026-08-08).
   display:none rather than a fold: .opts is a grid, so a collapsed row would
   still leave its 11px gap behind, and dead space is exactly what this change
   exists to remove. */
.opts.answered .opt.spent { display: none; }

/* The one destination offered at the moment of peak curiosity — right under
   the fact, beside Next. Never sold (VAL-12). */
.gf-inline { margin-top: 12px; }

/* ============================================================
   THE RESULT SCREEN — CEO design, 2026-08-08.
   The score is the receipt; the shelf is the point. Every pixel the
   score keeps is a pixel of shelf below the fold.
   ============================================================ */

/* --- the score band --- */
.card.rs { padding: 12px 14px; }
.rs-top { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rs-ring {
  flex: 0 0 auto; width: 72px; height: 72px; border-radius: 50%;
  display: grid; place-items: center;
  background: conic-gradient(var(--brand) calc(var(--pct) * 1%), rgba(255,255,255,.10) 0);
}
.rs-ring-in {
  width: 58px; height: 58px; border-radius: 50%; background: var(--bg2);
  display: grid; place-items: center; text-align: center; line-height: 1.12;
}
.rs-ring-in b { font-size: 19px; font-weight: 800; letter-spacing: -.02em; }
.rs-ring-in span { font-size: 8.5px; color: var(--muted); padding: 0 3px; }
.rs-meta { flex: 1 1 140px; min-width: 0; }
.rs-meta h2 { margin: 0 0 2px; font-size: 16.5px; letter-spacing: -.01em; }
.rs-streak { font-size: 13px; color: var(--muted); font-weight: 700; }
.rs-row { display: flex; align-items: center; gap: 10px; margin: 6px 0 4px; }
.rs-marks { display: flex; gap: 4px; }
.rs-mark {
  width: 20px; height: 20px; border-radius: 6px; display: grid; place-items: center;
  font-size: 11px; font-weight: 800;
}
.rs-mark.ok { background: rgba(79,214,163,.20); color: var(--good); border: 1px solid var(--good); }
.rs-mark.no { background: rgba(255,107,129,.18); color: var(--bad); border: 1px solid var(--bad); }
.rs-date { font-size: 11.5px; color: var(--muted); }
/* Compact, or it wraps to its own row on a 375px screen and the band grows
   from ~120px to 179px — 59px stolen from the shelf for one button. */
.rs-share { flex: 0 0 auto; min-height: 44px; padding: 0 12px; font-size: 13px; }
.rs-foot { margin-top: 14px; }

/* --- the shelf --- */
.card.shelf { margin-top: 14px; padding: 14px 14px 6px; }
.shelf-head h3 { margin: 0 0 2px; font-size: 16.5px; letter-spacing: -.01em; }
.shelf-head p { margin: 0 0 12px; font-size: 13px; color: var(--muted); }

/* TWO ROWS, NOT ONE — rebuilt 2026-08-09 from the CEO's phone.
   The card used to be a single horizontal row: thumbnail, then a column
   carrying badge, name, hook and every action button side by side. At 356px
   that column is ~250px, three buttons wanted more, and they ran straight out
   of the card. The hook was clamped to two lines to make room and was cut
   mid-sentence — so the one element whose entire job is to make someone tap
   could not finish its own thought.
   Now the picture and the words share the top row, and the actions get a row
   of their own at full card width. */
.topic {
  display: block;
  padding: 10px; margin-bottom: 9px; border-radius: 13px;
  background: var(--bg2); border: 1px solid var(--line); cursor: pointer;
}
.topic:hover { border-color: var(--brand); }
.topic:focus-within { border-color: var(--brand); }
.topic-top { display: flex; gap: 11px; align-items: flex-start; margin-bottom: 10px; }
/* Art: the real photograph of the real thing, from Wikimedia Commons, over a
   category tint that shows through when the network, the device or the URL
   fails. The tint carries no meaning, so it cannot mislead. */
.topic-art {
  flex: 0 0 64px; width: 64px; height: 64px;   /* fixed: flex-start, never stretched */
  border-radius: 10px; display: grid; place-items: center;
  background: linear-gradient(150deg, rgba(38,186,216,.20), rgba(124,108,255,.16));
  position: relative; overflow: hidden;
}
/* The verdict, as a mark on the corner of the picture. A ✓ and a ✗ are read
   the same way in every country we will ever ship to, so they need no
   translation and — the reason they are here — no line of their own. The word
   "CORRECT" cost a full row on every card (CEO, 2026-08-09). */
.topic-mark {
  position: absolute; z-index: 2; left: 0; bottom: 0;
  min-width: 22px; height: 22px; padding: 0 4px;
  display: grid; place-items: center;
  font-size: 13px; font-weight: 900; line-height: 1;
  border-radius: 0 9px 0 10px;
  background: var(--good); color: #08131a;
}
.topic.is-missed .topic-mark { background: var(--bad); color: #1a0a0d; }
.topic-emoji { font-size: 24px; line-height: 1; }
/* The photograph sits on top of the category tile, so a slow network, an
   offline device or a dead Commons URL all degrade to the tile rather than to
   a hole. The fallback is underneath, always — never toggled by script. */
.topic-art.has-pic { display: block; text-decoration: none; }
.topic-art.has-pic .topic-fallback {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 24px; line-height: 1;
}
.topic-art.has-pic img {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.topic-art.has-pic img[alt]:not([src]), .topic-art.has-pic img[src=""] { display: none; }
.topic-body { flex: 1 1 auto; min-width: 0; }
/* Name first, hook straight under it, both at the top of the card where the
   eye already is. The badge that used to push them down is now a mark on the
   picture. */
.topic-name { margin: 0 0 3px; font-size: 15.5px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
/* The hook runs in full. It was clamped to two lines to make room for buttons
   that no longer live beside it — and a hook cut mid-sentence ("about ninety
   kilos a day. On mil…") cannot pull anyone anywhere. Hooks are written to a
   100-character cap, so "in full" is three short lines at worst. */
.topic-hook { margin: 0; font-size: 13px; line-height: 1.45; color: var(--muted); }

/* FOUR SLOTS, FIXED. Two by two, equal widths, in the same order on every
   card in the app: Read · Visit · Watch · Sources. Before this the row held
   whichever destinations happened to exist, so the same word appeared in a
   different place on each card and the reader had to re-read the row every
   time (CEO, 2026-08-09).
   Equal columns via 1fr, and minmax(0,1fr) so a long French label shrinks its
   own text instead of widening the grid — the failure that pushed "Sources"
   past the card edge in the first place. */
.topic-ways {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px;
}
.way {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  text-decoration: none; min-width: 0;
  min-height: 40px; padding: 0 8px; border-radius: 9px;
  background: rgba(38,186,216,.09); border: 1px solid rgba(38,186,216,.28);
  color: var(--ink); font-size: 12.5px; font-weight: 700;
}
.way-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.way:hover { background: rgba(38,186,216,.18); border-color: var(--brand); }
.way-ico { flex: 0 0 auto; font-size: 14px; line-height: 1; }
/* A slot with nothing behind it is still drawn — that is what makes the
   absence readable, and what makes a new destination noticeable the day it
   arrives. It must never look tappable: no pointer, no hover, no focus, and
   flat enough that the difference is obvious at a glance rather than on
   inspection. */
.way.is-off {
  background: transparent; border-style: dashed;
  border-color: var(--line); color: var(--muted);
  opacity: .55; cursor: default; pointer-events: none;
}
.way.is-off .way-ico { filter: grayscale(1); }
@media (min-width: 480px) {
  .topic-ways { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 560px) {
  .topic-art { flex-basis: 96px; width: 96px; height: 96px; }
  .topic-emoji { font-size: 36px; }
}
.hcontrast .topic, .hcontrast .way { border-width: 2px; }
.hcontrast .way.is-off { opacity: .8; }

/* ============================================================
   THE ANSWERED CARD MUST FIT ON ONE SCREEN (CEO, 2026-08-11)
   "Everything should fit vertically on the screen without scrolling."
   Before: a flag question answered on a phone ran ~1,100px tall against a
   ~700px viewport — the fact, the source and Next were all below the fold and
   the reader had to hunt for them. Nothing here hides information; it takes
   space back from elements that have already done their job.
   ============================================================ */
/* During a live question the masthead becomes a strip. On a 360x640 phone the
   logo block alone was 70px of a 579px usable column (the tab bar takes the
   rest), which is what pushed Next underneath the tab bar. */
/* The answered card is a column sized to the screen. The fact — the one element
   whose length varies with the content — takes the leftover space and scrolls
   inside itself if it must; the destination and Next are pinned below it and
   are therefore ALWAYS visible. 100dvh, not vh: on a phone the address bar
   changes the viewport and vh lies about it. */
.answered-view {
  display: flex; flex-direction: column;
  /* max-height is set in JS from a real measurement — see choose() in app.js */
}
.answered-view .answerblock {
  display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto;
}
.answered-view .answerblock .fact {
  overflow-y: auto; min-height: 0; flex: 0 1 auto;
  -webkit-overflow-scrolling: touch;
}
.answered-view .answerfoot { flex: 0 0 auto; }
.answered-view .answerfoot .btnrow { margin-top: 10px; margin-bottom: 0; }
.answered-view .qart, .answered-view .qtext, .answered-view .opts { flex: 0 0 auto; }

.quiz-live .top { margin: 0 0 8px; }
.quiz-live .logo .markfull { height: 26px; }
.quiz-live .logo .namesub, .quiz-live .tag, .quiz-live .installbtn { display: none; }
.quiz-live .wrap { padding-top: 10px; }

/* The picture has served its purpose the moment the answer is in. A flag you
   have just identified does not need a quarter of the screen. */
.answered-view .qart { aspect-ratio: auto; height: 84px; margin: 6px 0 2px; }
.answered-view .qart-credit { display: none; }        /* credit stays on the file page, one tap away */
.answered-view .qtext { font-size: 17px; margin: 2px 0 10px; }
.answered-view .qcat { margin-bottom: 3px; }
/* Spent options collapse to nothing — the ones you did not pick carry no
   information once the answer is known. Only the right answer and, if you were
   wrong, your own pick survive. */
.answered-view .opts.answered { gap: 7px; }
.answered-view .opts.answered .opt { padding: 11px 13px; font-size: 15px; }
.answered-view .opts.answered .opt.spent { display: none; }
.answered-view .fact { margin-top: 11px; padding: 12px 13px; }
.answered-view .fact .btnrow { margin-top: 11px; }
/* Next is the last thing on the card and the widest — the thumb lands there
   without aiming, after the destination has had its chance to be seen. */
.answered-view .fact .btnrow #next { flex: 1 1 auto; }
@media (max-height: 780px) {
  .answered-view .qart { height: 64px; }
  .answered-view .qtext { font-size: 16px; margin: 2px 0 8px; }
  .answered-view .opts.answered .opt { padding: 9px 12px; font-size: 14.5px; }
  .answered-view .fact { font-size: 13.5px; padding: 11px 12px; }
}
/* Small phones (360x640 and the like) — measured: without this tier Next sat
   21px underneath the tab bar. Every value here was taken from that measurement,
   not guessed. */
@media (max-height: 700px) {
  .quiz-live .wrap { padding-top: 6px; }
  .quiz-live .top { margin-bottom: 6px; }
  .quiz-live .card { padding: 13px; }
  .answered-view .qart { height: 44px; margin: 4px 0 2px; }
  .answered-view .fact { margin-top: 9px; padding: 10px 11px; }
  .answered-view .fact .btnrow { margin-top: 9px; }
  .answered-view .fact .btn { padding: 11px 16px; }
  .answered-view .srclink { margin-top: 6px; }
  .answered-view .qtext { font-size: 15.5px; margin: 2px 0 7px; }
  .answered-view .opts.answered .opt { padding: 8px 11px; }
  .answered-view .gf-link { margin-top: 8px; padding: 9px 11px; }
}

/* A picture that IS the question — a flag to identify, a diagram to read.
   REBUILT 2026-08-10. The first version put every image inside a fixed 3:2 box
   with checkered padding, and rounded the BOX with overflow:hidden — which
   clipped the flag's own corners and left grey board visible around any flag
   that was not exactly 3:2. On a flag question a shaved corner or a hidden
   stripe can change the answer (CEO: "can lead to wrong answers if all colors
   are not visible").
   Now the frame adapts to the image: the container is invisible, the image
   sets its own height from its true aspect ratio, nothing is clipped, and the
   only chrome is a hairline border ON the image — which is also what keeps a
   white flag (Japan, Poland) visible against the dark card. */
.qart {
  margin: 10px 0 4px;
  display: flex; justify-content: center;
  background: none; border: none;
}
.qart img {
  display: block;
  width: 100%; height: auto;          /* the image decides its height */
  max-height: 42vh;                    /* one phone-screen budget, never more */
  max-width: 100%;
  object-fit: contain;
  border: 1px solid rgba(255,255,255,.35);
  border-radius: 6px;
  box-shadow: 0 2px 10px rgba(0,0,0,.35);
}
/* Portrait or square images (Nepal, Switzerland): height caps first, width
   follows — width:auto stops the border stretching past the visible image. */
.qart.is-contain img { width: auto; max-width: 100%; }
.qart-credit { font-size: 10.5px; color: var(--muted); margin: 0 0 2px; text-align: right; }
.qart-credit a { color: inherit; }
@media (min-width: 560px) { .qart img { max-height: 300px; } }

/* The country select. A native control on purpose — a phone gives it its own
   search, scroll and screen-reader behaviour for free, and 200 options is
   exactly where a custom widget starts costing more than it gives. Sized to
   the 44px touch target and stopped from overflowing its card. */
.cselect {
  display: block; width: 100%; max-width: 100%; min-width: 0;
  min-height: 44px; padding: 0 12px; margin: 0 0 4px;
  border-radius: 11px; border: 1px solid var(--line);
  background: var(--bg2); color: var(--ink);
  font: inherit; font-size: 15px;
}
.cselect:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
.onb .cselect { margin: 4px 0 14px; text-align: center; text-align-last: center; }
.hcontrast .cselect { border-width: 2px; }

/* Keep exploring — the sideways lanes under the shelf. Scrolls horizontally
   so six lanes never push the shelf off the screen; the partly-visible last
   tile is the signal that there is more, which is cheaper than a button. */
.keep { margin-top: 4px; padding-top: 14px; border-top: 1px solid var(--line); }
.keep-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.keep-head h3 { margin: 0 0 2px; font-size: 15.5px; letter-spacing: -.01em; }
.keep-head p { margin: 0 0 12px; font-size: 12.5px; color: var(--muted); }
.surprise {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  min-height: 40px; padding: 0 12px; border-radius: 999px; cursor: pointer;
  background: rgba(255,143,163,.10); border: 1px solid rgba(255,143,163,.40);
  color: var(--brand2); font: inherit; font-size: 12.5px; font-weight: 700; white-space: nowrap;
}
.surprise:hover { background: rgba(255,143,163,.18); border-color: var(--brand2); }
/* Illustrated mode cards on the Train tab. The picture sits behind the copy
   under a wash, so the card reads as a product and not a settings row. */
.card.mode.has-art { position: relative; overflow: hidden; }
.card.mode.has-art > .mode-art {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.card.mode.has-art > .mode-wash {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,10,24,.62) 0%, rgba(8,10,24,.84) 100%);
}
.card.mode.has-art > *:not(.mode-art):not(.mode-wash) { position: relative; z-index: 1; }
.hcontrast .card.mode.has-art > .mode-wash { background: rgba(0,0,0,.86); }

/* Picker tiles — categories and sub-categories with a face. A pill said the
   word; a tile shows what is behind it. Same aria-pressed semantics as the
   chips they replace, so nothing changes for a screen reader. */
.ptiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
@media (min-width: 560px) { .ptiles { grid-template-columns: repeat(4, 1fr); } }
.ptile {
  position: relative; overflow: hidden; cursor: pointer; padding: 0;
  height: 62px; border-radius: 11px; background: var(--bg2);
  border: 1px solid var(--line); color: #fff; font: inherit; text-align: left;
}
.ptile:hover { border-color: var(--brand); }
.ptile:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.ptile-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ptile-wash {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,10,24,.34) 0%, rgba(8,10,24,.80) 100%);
}
.ptile:not(.has-art) .ptile-wash {
  background: linear-gradient(150deg, rgba(38,186,216,.28), rgba(124,108,255,.26)), rgba(8,10,24,.55);
}
.ptile-label {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 7px 8px;
  font-size: 11.5px; font-weight: 800; line-height: 1.15;
}
/* Selected: the brand ring plus a lifted wash, so it does not depend on colour
   alone for anyone who cannot see the tint. */
.ptile[aria-pressed="true"] { border-color: var(--brand); box-shadow: inset 0 0 0 2px var(--brand); }
.ptile[aria-pressed="true"] .ptile-wash { background: linear-gradient(180deg, rgba(38,186,216,.30) 0%, rgba(8,10,24,.82) 100%); }
.hcontrast .ptile { border-width: 2px; }

/* City search */
.citysearch {
  width: 100%; min-height: 44px; margin-bottom: 12px; padding: 0 12px;
  border-radius: 10px; background: var(--bg2); border: 1px solid var(--line);
  color: var(--ink); font: inherit; font-size: 14px;
}
.citysearch:focus { outline: none; border-color: var(--brand); }
.citynone { margin: 10px 0 0; }

/* Six doors. A grid, so nothing is ever half-cut at the edge of a scroller —
   the cut-off tile was the single most-repeated complaint and it was caused by
   a horizontal row that could not fit. Two up on a phone, three on a tablet.
   (CEO, 2026-08-09.) */
.doors { display: grid; grid-template-columns: repeat(2, 1fr); gap: 9px; margin-top: 12px; }
@media (min-width: 560px) { .doors { grid-template-columns: repeat(3, 1fr); } }
.door {
  position: relative; overflow: hidden; cursor: pointer; padding: 0;
  height: 104px; border-radius: 12px; background: var(--bg2);
  border: 1px solid var(--line); color: #fff; font: inherit; text-align: left;
}
.door:hover { border-color: var(--brand); }
.door:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.door-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.door-wash {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,10,24,.28) 0%, rgba(8,10,24,.62) 55%, rgba(8,10,24,.90) 100%);
}
.door:not(.has-art) .door-wash {
  background: linear-gradient(150deg, rgba(38,186,216,.30), rgba(124,108,255,.28)), rgba(8,10,24,.55);
}
.door-body { position: absolute; left: 0; right: 0; bottom: 0; padding: 9px 10px;
  display: flex; flex-direction: column; gap: 2px; }
.door-ico { font-size: 17px; line-height: 1; }
.door-label { font-size: 12.5px; font-weight: 800; line-height: 1.2; }
.door-count { font-size: 10.5px; opacity: .8; }
.hcontrast .door { border-width: 2px; }
.hcontrast .door-wash { background: rgba(0,0,0,.82); }

/* Behind a door: a grid with room, never a clipped row. */
.dgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (min-width: 560px) { .dgrid { grid-template-columns: repeat(3, 1fr); } }
.dgrid .dcard-sm { width: auto; }

/* Shelves. Horizontal inside a shelf, vertical between them: one flick browses
   a subject, one scroll changes appetite. The last card is deliberately part-
   visible — that peek is the affordance, and it is cheaper than a button. */
.rack { margin-top: 14px; }
.rack-head { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; }
.rack-ico { font-size: 15px; line-height: 1; }
.rack-head h4 { margin: 0; font-size: 13px; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted); }
.rack-row {
  display: flex; gap: 9px; overflow-x: auto; padding-bottom: 6px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.rack-row::-webkit-scrollbar { display: none; }
.rack-row > * { scroll-snap-align: start; }

/* A discovery card: photograph, name, and the reason to care. The whole card
   is one tap — no Read/Explore/More trio all going to the same place. */
.dcard {
  position: relative; flex: 0 0 auto; overflow: hidden; cursor: pointer;
  border-radius: 12px; background: var(--bg2); border: 1px solid var(--line);
  color: #fff; text-align: left;
}
.dcard:hover { border-color: var(--brand); }
.dcard:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.dcard-sm { width: 156px; }
.dcard-lg { width: 100%; }
/* Fixed heights on a full-width card crop the photograph into a letterbox
   strip — a 150px band across a 684px card is 4.5:1, and reads as stretched
   even though object-fit is cropping, not distorting (CEO, desktop, 2026-08-08).
   Aspect ratio instead, so the picture keeps its shape at every width. */
.dcard-art { position: relative; width: 100%; height: 96px; background: var(--bg2); }
.dcard-lg .dcard-art { height: auto; aspect-ratio: 16 / 9; }
@supports not (aspect-ratio: 1) { .dcard-lg .dcard-art { height: 200px; } }
.dcard-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dcard-wash {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,10,24,.05) 40%, rgba(8,10,24,.55) 100%);
}
.dcard-body { padding: 9px 10px 11px; }
.dcard-title { margin: 0 0 3px; font-size: 13.5px; font-weight: 800; line-height: 1.25;
  letter-spacing: -.01em; color: var(--ink); }
.dcard-lg .dcard-title { font-size: 17px; }
/* Two lines. The hook exists to pull, not to inform — if it answers the
   question, there is no reason to tap. */
.dcard-hook {
  margin: 0; font-size: 12px; line-height: 1.4; color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.dcard-lg .dcard-hook { font-size: 13.5px; -webkit-line-clamp: 3; }
.surprise-slot:empty { display: none; }
.surprise-slot { margin-top: 10px; }
.dcard.is-surprise { border-color: var(--brand2); }
.hcontrast .dcard { border-width: 2px; }
@media (min-width: 560px) { .dcard-sm { width: 190px; } .dcard-sm .dcard-art { height: 116px; } }

/* Covers, not buttons. A photograph under a dark wash, the label sitting on
   it — the row should read like a shelf you glance along, which is the whole
   point of the window-shopping idea. */
.lane {
  position: relative; flex: 0 0 auto; width: 116px; height: 96px;
  display: block; overflow: hidden; text-decoration: none;
  border-radius: 12px; background: var(--bg2);
  border: 1px solid var(--line); color: #fff;
}
.lane:hover { border-color: var(--brand); }
.lane-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The wash is what stops it looking like a stock-photo grid: the image is
   atmosphere, the words are the message. Present even without a photo, so the
   label contrast is identical either way. */
.lane-wash {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,10,24,.30) 0%, rgba(8,10,24,.62) 52%, rgba(8,10,24,.90) 100%);
}
.lane:not(.has-art) .lane-wash {
  background: linear-gradient(150deg, rgba(38,186,216,.30), rgba(124,108,255,.28)), rgba(8,10,24,.55);
}
.lane-body {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 8px 9px;
  display: flex; flex-direction: column; gap: 3px;
}
.lane-ico { font-size: 17px; line-height: 1; }
.lane-label { font-size: 11.5px; font-weight: 800; line-height: 1.2; letter-spacing: .01em; }
.hcontrast .lane { border-width: 2px; }
.hcontrast .lane-wash { background: rgba(0,0,0,.82); }
@media (min-width: 560px) { .lane { width: 140px; height: 112px; } .lane-label { font-size: 12.5px; } }

/* Go further — the inline destination beside a fact (D-061). */
.gofurther { margin-top: 14px; }
.gf-item { padding: 12px 0; border-top: 1px solid var(--line); }
.gf-item:first-of-type { border-top: 0; padding-top: 4px; }
.gf-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.gf-mark { color: var(--bad, #ff6b6b); font-weight: 800; font-size: 15px; line-height: 1; }
.gf-name { font-weight: 700; font-size: 15.5px; letter-spacing: -.01em; }
.gf-missed .gf-name { color: var(--ink); }
.gf-item:not(.gf-missed) .gf-name { color: var(--muted); font-weight: 600; }
.gf-links { display: grid; gap: 7px; }
.gf-link { display: flex; align-items: center; gap: 10px; text-decoration: none;
  padding: 10px 12px; border-radius: 11px; background: rgba(38,186,216,.07);
  border: 1px solid rgba(38,186,216,.22); color: var(--ink); font-size: 14px; line-height: 1.35; }
.gf-link:hover { background: rgba(38,186,216,.14); border-color: var(--brand); }
.gf-ico { font-size: 17px; line-height: 1; flex: 0 0 auto; }
.gf-text { flex: 1 1 auto; min-width: 0; }
.gf-sub { display: block; color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.gf-go { flex: 0 0 auto; color: var(--brand); font-weight: 700; }
.gf-note { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); opacity: .75; }
.rmotion .gf-link { transition: none; }

/* Fact or Fake */
.truthbtns { display: grid; gap: 11px; }
.truthopt { font-size: 16px; }

/* City packs */
.citycard { cursor: pointer; }
.cityrow { display: flex; align-items: center; gap: 12px; }
.cityemoji { font-size: 30px; line-height: 1; }
.citycard h3 { margin: 0; font-size: 18px; }
.citycard p { margin: 10px 0 0; color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.phrase { padding: 10px 0; border-bottom: 1px solid var(--line); }
.phrase:last-child { border-bottom: none; }
.phrase-main { font-size: 16px; }
.phrase-main b { font-weight: 700; }
.tips { list-style: none; margin: 6px 0 0; padding: 0; }
.tips li { position: relative; padding: 8px 0 8px 24px; border-bottom: 1px solid var(--line); font-size: 14px; line-height: 1.5; }
.tips li:last-child { border-bottom: none; }
.tips li::before { content: "•"; position: absolute; left: 6px; color: var(--brand); font-weight: 800; }
.regionrow { margin-top: 10px; }

/* Recall (explain it back) */
.recall { margin-top: 4px; }
.recallrow { display: flex; gap: 10px; }
.recallinput { flex: 1; font-family: var(--font); font-size: 16px; color: var(--ink); background: var(--card2); border: 1.5px solid var(--line); border-radius: 12px; padding: 13px 14px; }
.recallinput:focus { outline: none; border-color: var(--accent); }

/* Header gear + speak buttons */
.gearbtn { appearance: none; cursor: pointer; background: var(--card); border: 1px solid var(--line); color: var(--ink); font-size: 16px; padding: 7px 11px; border-radius: 999px; margin-left: auto; margin-right: 10px; }
.gearbtn:hover { border-color: var(--accent); }
.speakbtn { appearance: none; cursor: pointer; background: var(--card2); border: 1px solid var(--line); border-radius: 8px; font-size: 15px; padding: 3px 8px; vertical-align: middle; }
.speakbtn:hover { border-color: var(--accent); }

/* Focus visibility (keyboard users) */
button:focus-visible, a:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 8px; }

/* ---- Comfort modes (classes on <html>) ---- */
/* Text size: base CSS is px-based, so scale the whole page. */
.fs-large body { zoom: 1.15; }
.fs-xl body { zoom: 1.3; }

/* Dyslexia-friendly reading */
.dyslexia body { font-family: Verdana, Tahoma, "Segoe UI", sans-serif; }
.dyslexia .qtext { letter-spacing: .035em; word-spacing: .16em; line-height: 1.65; font-weight: 600; }
.dyslexia .opt, .dyslexia .fact, .dyslexia p { letter-spacing: .03em; word-spacing: .14em; line-height: 1.7; }

/* Reduced motion (also honor the OS preference automatically) */
.rmotion *, .rmotion *::before, .rmotion *::after { transition: none !important; animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* High contrast */
.hcontrast { --ink: #ffffff; --muted: #d5d9f5; --line: #9aa1e8; --card: #14162e; --card2: #1c1f3f; }
.hcontrast body { background: #05060f; }
.hcontrast .card { background: var(--card); border-width: 2px; box-shadow: none; }
.hcontrast .opt { border-width: 2px; }
.hcontrast .fact { background: #23205a; border-color: var(--accent); }
.hcontrast .opt.correct { background: #0d3f2c; border-color: #6fffc4; }
.hcontrast .opt.wrong { background: #48141f; border-color: #ff9db0; }

/* Install affordances */
.installbtn {
  appearance: none; cursor: pointer; font-family: var(--font); font-weight: 800; font-size: 13px;
  color: #17162b; background: var(--brand);
  border: none; padding: 8px 14px; border-radius: 999px; margin-left: auto; margin-right: 12px;
}
.installbtn:hover { filter: brightness(1.06); }
.iosbanner {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 50;
  display: flex; align-items: center; gap: 12px; max-width: 700px; margin: 0 auto;
  background: var(--card); border: 1px solid var(--accent); border-radius: 14px;
  padding: 13px 15px; font-size: 14px; box-shadow: var(--shadow);
}
.iosbanner b { color: var(--brand); }
.iosbanner button { margin-left: auto; background: transparent; border: none; color: var(--muted); font-size: 16px; cursor: pointer; }
.done-badge { font-size: 13px; color: var(--good); font-weight: 700; }
/* Onboarding (FEAT-011) */
.onb { text-align: center; padding: 34px 22px; }
.onb-emoji { font-size: 54px; line-height: 1; margin-bottom: 12px; }
.onb-title { font-size: 24px; margin: 0 0 10px; color: var(--ink); }
.onb-text { color: var(--muted); font-size: 15px; line-height: 1.6; max-width: 440px; margin: 0 auto 18px; }
.onb-dots { margin-bottom: 16px; }
.onb-dot { display: inline-block; width: 8px; height: 8px; border-radius: 99px; background: var(--card2); margin: 0 4px; }
.onb-dot.on { background: var(--brand); }

/* brand motto under the wordmark (D-001b: Qpio) */
.logo{flex-wrap:wrap}
.logo .motto{flex-basis:100%;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;opacity:.55;margin-top:1px;font-style:italic}

/* D-055: founder's Brain-Infinity mark replaces the owl */
.logo img.mark{height:26px;width:auto;display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.35))}

/* FEAT-027: mobile tab shell. Bar exists only under 900px; desktop keeps the
   single flow untouched. 44px+ targets, safe-area padding for iOS. */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; justify-content: space-around; align-items: stretch;
  background: rgba(11, 34, 51, .96); backdrop-filter: blur(10px);
  border-top: 1px solid var(--line);
  padding: 6px max(8px, env(safe-area-inset-left)) calc(6px + env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-right));
}
.tabbtn {
  flex: 1 1 0; min-height: 48px; max-width: 130px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  background: none; border: 0; border-radius: 12px; cursor: pointer;
  color: var(--muted); font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .02em;
}
.tabbtn .ticon { font-size: 20px; line-height: 1; }
.tabbtn img.ticon { height: 22px; width: auto; filter: grayscale(1) opacity(.65); }
.tabbtn[aria-current="page"] { color: var(--brand); background: rgba(38, 186, 216, .1); }
.tabbtn[aria-current="page"] img.ticon { filter: none; }
.resumebar {
  position: fixed; left: 50%; transform: translateX(-50%); z-index: 41;
  bottom: calc(64px + env(safe-area-inset-bottom));
  min-height: 44px; padding: 10px 22px; border-radius: 999px; border: 1px solid var(--brand);
  background: var(--card); color: var(--brand); font: inherit; font-weight: 800; font-size: 14px;
  box-shadow: var(--shadow); cursor: pointer;
}
/* room so the fixed bar never covers the last card */
body:has(.tabbar:not(.hidden)) .wrap { padding-bottom: 120px; }
@media (min-width: 900px) {
  /* CEO 2026-08-02: phone and web look the same - the bar stays, centred.
     The bar must share .wrap's box exactly (720px, 18px side padding) or the
     four tabs sit on a different grid from the cards above them and the
     footer pokes out beside it — visible on desktop, 2026-08-08. */
  .tabbar {
    left: 50%; right: auto; transform: translateX(-50%);
    width: min(720px, 100%);
    padding-left: 18px; padding-right: 18px;
    justify-content: space-between;
    border-radius: 16px 16px 0 0; border-left: 1px solid var(--line); border-right: 1px solid var(--line);
  }
  .tabbtn { max-width: none; }
  /* the footer belongs above the bar, not behind it */
  body:has(.tabbar:not(.hidden)) .wrap { padding-bottom: 140px; }
}

/* v23: full logo in the header; the wordmark steps back (CEO 2026-08-03) */
.logo{flex-direction:column;align-items:flex-start;gap:2px}
.logo img.markfull{height:40px;width:auto;filter:drop-shadow(0 1px 3px rgba(0,0,0,.4))}
.logo .namesub{font-size:clamp(10px,2.9vw,13px);font-weight:700;letter-spacing:.05em;color:var(--muted)}
/* The motto gets its own line — on a phone it used to wrap mid-phrase
   ("Qpio · Quaero, ergo / Sapio"). CEO, 2026-08-06. */
.logo .namesub .motto2{display:block;font-style:italic;font-weight:500;letter-spacing:.10em;opacity:.75;white-space:nowrap}
