/* ===================== Bibellinjen — Design System ===================== */
/* Warm, modern, earthy board-game aesthetic. Update the tokens below to retheme. */

@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Lato-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Lato";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Lato-Italic.woff2") format("woff2");
}
@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/Lato-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("fonts/Lato-Black.woff2") format("woff2");
}

:root {
  /* Palette */
  --color-bg: #F7F1E4;
  --color-bg-alt: #EFE6D3;
  --color-surface: #FFFDF8;
  --color-text: #3A3226;
  --color-text-muted: #7A6F5C;
  --color-accent: #9a4f03;
  --color-accent-dark: #6d3904;
  --color-accent-soft: #EBD9A0;
  --color-success: #5C8A5C;
  --color-danger: #B4553F;
  --color-border: #E3D6B8;

  /* Layout */
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --shadow-sm: 0 1px 3px rgba(58, 50, 38, 0.12);
  --shadow-md: 0 6px 20px rgba(58, 50, 38, 0.16);
  --font-sans: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Card sizing — driven by viewport height so landscape (the intended mobile
     orientation) yields large cards even though width is unconstrained and
     height is the scarce dimension. Capped so desktop cards don't balloon. */
  --card-w: clamp(85px, 21vh, 135px);
  --card-h: clamp(130px, 34vh, 210px);

  /* Shared typography so the book title reads identically on the front and
     the flipped-back face. */
  --card-title-size: clamp(11px, 3.4vh, 15px);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overscroll-behavior: none;
}

body {
  font-family: var(--font-sans);
  background: var(--color-bg);
  color: var(--color-text);
  -webkit-tap-highlight-color: transparent;
  /* Without these, dragging/tapping a card races against iOS Safari's own
     built-in long-press behavior — text selection plus its magnifying-glass
     loupe — since nothing here told it this is a game surface, not
     selectable text. touch-callout also suppresses the "Copy / Look Up"
     popup menu iOS shows on long-press. Re-enabled below for actual text
     inputs, where normal select/copy behavior is still wanted. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

input,
textarea {
  -webkit-touch-callout: default;
  -webkit-user-select: text;
  user-select: text;
}

#app {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 { margin: 0; font-weight: 700; }
p { margin: 0; }

button {
  font-family: inherit;
  cursor: pointer;
}

.hidden { display: none !important; }

/* ===================== Screens ===================== */

.screen {
  display: none;
  flex: 1;
  flex-direction: column;
  padding: 20px 16px calc(20px + env(safe-area-inset-bottom));
  min-height: 100vh;
  min-height: 100dvh;
}

.screen.active {
  display: flex;
}

/* ===================== Welcome screen ===================== */

#screen-welcome {
  position: relative;
}

.welcome-info-btn {
  position: absolute;
  top: calc(16px + env(safe-area-inset-top));
  right: 16px;
  font-size: 20px;
  opacity: 0.7;
}

.welcome-info-btn:hover {
  opacity: 1;
}

.welcome-content {
  margin: auto;
  width: 100%;
  max-width: 420px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

/* Deliberately understated — a copyright line + a way to find the About
   screen shouldn't compete with the actual game buttons for attention.
   Capped at the same max-width as .welcome-content and centered the same
   way, so its right edge lines up with the logo/buttons column above it —
   without this, on a wide desktop viewport .welcome-footer (a plain
   full-bleed sibling of that column, not a descendant of it) stretched
   edge-to-edge and pinned its text to the actual browser window's right
   edge, far from the centered content instead of sitting next to it. */
.welcome-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  padding: 18px calc(16px + env(safe-area-inset-right)) env(safe-area-inset-bottom) 16px;
  font-size: 12px;
  color: var(--color-text-muted);
}

.welcome-footer-link {
  background: none;
  border: none;
  padding: 0;
  color: var(--color-text-muted);
  font-size: 12px;
  text-decoration: underline;
  cursor: pointer;
}

.welcome-footer-link:hover {
  color: var(--color-accent);
}

/* Hidden everywhere except narrow portrait phones (media query below) —
   Complete mode's card-dragging needs more width than portrait offers, so
   this nudges players toward landscape up front rather than leaving them
   to hit that friction mid-game. */
.rotate-hint {
  display: none;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  background: var(--color-accent-soft);
  border: 2px solid var(--color-accent);
  border-radius: var(--radius-md);
  color: var(--color-accent-dark);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.35;
  text-align: left;
}

.rotate-hint-icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  animation: rotate-hint-spin 2.4s ease-in-out infinite;
}

/* A portrait phone icon rotating to landscape and back — a visual echo of
   the instruction, not just text. */
@keyframes rotate-hint-spin {
  0%, 12% { transform: rotate(0deg); }
  42%, 58% { transform: rotate(-90deg); }
  88%, 100% { transform: rotate(0deg); }
}

@media (max-width: 640px) and (orientation: portrait) {
  .rotate-hint { display: flex; }
}

.app-title-wrap {
  position: relative;
  line-height: 0; /* collapse the h1's inline-box gap so the image sits flush */
  margin-bottom: 50px;
  /* Lets .app-logo-text size itself in cqw, so the wordmark scales exactly
     with the rendered logo width instead of drifting out of the red-stroke
     frame at in-between viewport sizes. */
  container-type: inline-size;
}

.app-logo {
  display: block;
  width: 100%;
  max-width: 420px;
  height: auto;
  margin: 0 auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

/* The wordmark used to be baked into the logo image (fixed to Swedish).
   Now the image (assets/logo-bg-*.png) is background art only — a red
   stroke frame with no text — and this renders the real, translatable
   title on top of it. left/right are tuned per background image (see the
   mobile override below) so the text can never cross the red stroke:
   logo-bg-wide.png's inner frame needs >=340px right padding at its native
   1506px width (22.58%), logo-bg-short.png's needs >=130px at 1080px
   (12.04%) — measured directly against the red stroke pixels in each PNG. */
.app-logo-text {
  position: absolute;
  top: 54.5%;
  left: 25.36%;
  right: 22.58%;
  transform: translateY(-50%);
  color: #fcfeee;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  pointer-events: none;
  font-size: 7.6cqw;
}

@media (max-width: 640px) {
  .app-logo-text {
    left: 15.65%;
    right: 12.04%;
    font-size: 10.6cqw;
  }
}

.app-subtitle {
  color: var(--color-text-muted);
  font-size: 16px;
  margin-top: -16px;
}

.welcome-buttons {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Grouped into two rows so mobile (below) can arrange primary/secondary
   buttons side by side instead of one tall column — on wider screens these
   just look like plain continuation of the same vertical stack, since both
   groups share the outer gap above. */
.welcome-buttons-primary,
.welcome-buttons-secondary {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* ===================== Buttons ===================== */

.btn {
  border: none;
  border-radius: var(--radius-md);
  padding: 15px 20px;
  font-size: 16px;
  font-weight: 600;
  transition: transform 0.12s ease, box-shadow 0.12s ease, opacity 0.12s ease;
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn:active {
  transform: scale(0.97);
}

.btn-primary {
  background: var(--color-accent);
  color: var(--color-surface);
  box-shadow: var(--shadow-sm);
}

.btn-primary:hover { background: var(--color-accent-dark); }

/* Larger start-game buttons with a bigger title line + smaller descriptive
   subtitle line, e.g. "Start game — Standard" / "Five cards at a time". */
.btn-two-line {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 18px 20px 20px;
}

.btn-title {
  font-size: 19px;
  font-weight: 700;
  line-height: 1.2;
}

.btn-subtitle {
  font-size: 13px;
  font-weight: 500;
  opacity: 0.9;
  line-height: 1.2;
}

.btn-secondary {
  background: transparent;
  color: var(--color-text);
  border: 2px solid var(--color-border);
}

.btn-secondary:hover { border-color: var(--color-accent); }

/* Icon + label centered together as one unit by default — on a wide
   desktop button, pinning them to the left edge (like the mobile layout
   below) leaves a lopsided slab of empty space on the right and reads as
   misaligned rather than intentional. Mobile switches this back to
   left-aligned (see the portrait media query) where the button is barely
   wider than its content, so the "drop cap" look actually applies. */
.btn-icon-label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

.btn-icon-prefix {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: inherit;
}

/* Language field label: same icon-then-text pattern as the buttons above,
   just smaller and inline since it's a field label, not a button. */
.field-label-icon-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}

.field-label-icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: inherit;
}

.btn-danger {
  background: var(--color-danger);
  color: var(--color-surface);
}

.btn-icon {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-sm);
  width: 40px;
  height: 40px;
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text);
}

.btn-icon:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/*#btnStartLong {
background: var(--color-accent-dark);
}*/

/* ===================== Game header ===================== */

.game-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}

.game-header-stats {
  flex: 1;
  display: flex;
  justify-content: space-between;
  gap: 8px;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 10px 16px;
  box-shadow: var(--shadow-sm);
}

.stat {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  white-space: nowrap;
}

.game-instructions {
  text-align: center;
  color: var(--color-text-muted);
  font-size: 14px;
  margin: 0;
}

/* Groups instructions + cards + actions as one unit, centred in the space
   below the header — keeps the confirm/next-round button close to the
   cards instead of pinned to the bottom edge of the screen. */
.game-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  width: 100%;
  min-height: 0;
}

.game-actions {
  display: flex;
  justify-content: center;
}

.game-actions .btn { min-width: 200px; }

/* ===================== Cards ===================== */

.hand {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  min-height: calc(var(--card-h) + 20px);
  touch-action: none;
}

/* Standard mode hand: cards are absolutely positioned so drag-to-reorder
   can animate neighbours sliding aside via inline `left`. */
.hand.draggable {
  display: block;
  height: var(--card-h);
}

.hand.draggable .card {
  position: absolute;
  top: 0;
  left: 0;
  touch-action: none;
}

.card {
  width: var(--card-w);
  height: var(--card-h);
  flex-shrink: 0;
  perspective: 1200px;
  position: relative;
  transition: transform 0.25s ease;
}

.card.dragging {
  transition: none;
  z-index: 20;
  cursor: grabbing;
}

/* Complete mode, while a card is being actively dragged — either the
   pending card being dropped into the line (attachLongPendingDrag) or an
   already-placed but unresolved card being picked back up and repositioned
   (attachUnresolvedCardInteraction). position:fixed lets it move freely
   between separate containers (pending section vs. line, which sit side by
   side on mobile). !important: for the reposition case the card is a
   descendant of `.long-line .card { position: absolute; }` (below) — same
   two-class specificity, and that rule comes later in the file, so without
   !important here it silently won on ties, leaving the card position:absolute
   instead of position:fixed. Bug symptom was exactly that: dragging an
   unresolved card showed no visible movement (its left/top were being
   interpreted relative to the line, not the viewport), even though the
   drop still landed correctly since the actual reorder logic never
   depended on the visual position. pointer-events:none is what lets
   elementFromPoint "see through" this card to find the slot underneath it
   while dragging. */
.card.dragging-pending {
  position: fixed !important;
  z-index: 200;
  margin: 0;
  pointer-events: none;
  transition: none;
  box-shadow: var(--shadow-md);
  cursor: grabbing;
}

.card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform 0.7s cubic-bezier(0.34, 1.3, 0.4, 1);
  transform-style: preserve-3d;
}

.card.flipped .card-inner {
  transform: rotateY(180deg);
}

.card-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 8px 6px;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.card-front-title,
.card-back .card-title {
  font-weight: 700;
  /* --title-size is set per-card in JS (makeHandDraggable's measure(), see
     ui.js) from the card's actual rendered width — Standard mode shrinks
     that width in JS to fit 5 across, and --card-title-size alone (a
     viewport-height-driven CSS var) has no way to know about that shrink,
     so at narrow widths it kept text far too big for the box. Falls back
     to --card-title-size for any card measure() hasn't touched. */
  font-size: var(--title-size, var(--card-title-size));
  line-height: 1.25;
  overflow-wrap: break-word;
  word-break: break-word;
  /* manual (not auto): book titles already carry hand-placed soft hyphens
     (­, U+00AD) at the exact syllable break the data intends — e.g.
     "Tessaloni­kerbrevet". hyphens:auto additionally consults the
     browser's own Swedish dictionary and can override that placement with
     a linguistically-valid but undesired point of its own (it chose
     "Tessaloni-/kerbrevet" over the inserted "Tessaloniker-/brevet").
     manual restricts breaking to only those explicit soft hyphens. */
  hyphens: manual;
}

.card-back .card-title {

  margin-bottom: 15px;
}

/* Shared background-art template (assets/cards/fronts/front-bg.jpg) until
   each book gets its own unique illustration — same idea as the category
   art on the back, just one shared image for now. The title sits in the
   template's plain band (measured the same way as the back's circle/box). */
.card-front {
  display: block;
  background-image: url('assets/cards/fronts/front-bg.jpg');
  background-size: cover;
  background-position: center;
  background-color: var(--color-surface);
  border: 2px solid var(--color-accent-soft);
  cursor: grab;
}

.card-front-title {
  position: absolute;
  left: 10%;
  right: 10%;
  /* Widened from the template's original ~19%-tall band (33.5%/47.6%,
     centred on the template's printed white label at ~43% from the top)
     — with hyphens:manual respecting real book titles rather than being
     free to pick a shorter dictionary break, some two-word titles need 3
     lines (e.g. "Första" + a hyphenated "Tessaloniker-"/"brevet"), which
     clipped in the original band at any card size. A taller band costs
     nothing visually — it just covers more of the shared decorative
     background — and works at every breakpoint without duplicating this
     per media query. Kept centred on that same ~43% midpoint (not just
     widened downward) so the text doesn't drift off the printed label. */
  top: 11%;
  bottom: 25%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--color-text);
  overflow: hidden;
}

/* The printed-card background art (assets/cards/backs/*.jpg, one per
   category) supplies the number circle and chapter-count box graphics, so
   text is absolutely positioned on top of them rather than flowing in a
   flex column. Percentages were measured directly from the template PNGs
   and are consistent across all 9 category backgrounds. background-color
   is a same-family fallback swatch, visible only if the image fails to
   load. */
.card-back {
  display: block;
  transform: rotateY(180deg);
  background-size: cover;
  background-position: center;
  color: var(--color-text);
}

.card-back-number {
  position: absolute;
  left: 49.6%;
  top: 14.6%;
  transform: translate(-50%, -50%);
  color: #fff;
  /* Tied to --card-w (the circle's own diameter is 25.5% of --card-w) rather
     than viewport height directly — those two used to scale independently,
     so at some viewport sizes the number outgrew the circle it sits in. */
  font-size: clamp(14px, calc(var(--card-w) * 0.163), 24px);
  font-weight: 800;
  line-height: 1;
}

.card-back-content {
  display: flex;
  position: absolute;
  /* Matches .card-front-title's available width exactly (10% side padding
     plus its 2px border, which .card-front has but .card-back doesn't) —
     otherwise the same title wraps differently front vs back purely from
     one side having a bit more room, greedily fitting a hyphenated
     fragment on the last line where the other side plain-wraps at a
     space instead (e.g. "Tredje Johannesbrevet" showed as hyphenated on
     the back but not the front, despite being the same title/font-size). */
  left: calc(10% + 2px);
  right: calc(10% + 2px);
  top: 25%;
  bottom: 18%;
  flex-direction: column;
  align-items: center;
  text-align: center;
  overflow: hidden;
}

/* Title/quote centre themselves in whatever space is left once
   .card-back-bottom (below) has taken what it needs — flex:1 lets this
   group claim all the remaining height in .card-back-content, so type/
   testament always end up pinned to the very bottom of that box
   (touching .card-back-chapters right underneath it) regardless of
   whether the quote is showing. min-height guarantees at least 2 lines
   of title (reusing --title-size, the same variable that already drives
   the title's own font-size — see .card-front-title/.card-back .card-title
   above) — without it, a long two-word title (e.g. "Första Samuelsboken")
   on a narrow 5-across card could get squeezed by .card-back-bottom to
   less than one line's height and clip instead of just wrapping normally. */
.card-back-top {
  flex: 1;
  /* *2.3 rather than a literal *2 — small rounding buffer, since browsers
     don't always render a text line's actual box at the exact
     font-size*line-height math at very small sizes (a handful of sub-pixel
     rounding artifacts becomes proportionally bigger at, say, 7px). */
  min-height: calc(var(--title-size, var(--card-title-size)) * 1.25 * 2.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  overflow: hidden;
}

.card-back-bottom {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.card-back .card-title {
  color: var(--color-text);
}

/* Quotes are too small to read comfortably at the small in-hand/in-line
   card size used during gameplay, so they're hidden there entirely —
   #referenceCardWrap below (the "browse the cards" screen, outside of
   gameplay) is the only place they're shown, at a card size built for it. */
.card-back .card-quote {
  display: none;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
  font-size: clamp(8px, 2vh, 10px);
  font-style: italic;
  font-weight: 400;
  line-height: 1.3;
  margin-top: 4px;
  padding: 0 3px;
  color: var(--color-text);
}

/* The reference/browse screen's cards are already sized to be read
   comfortably (see #screen-reference's --card-w/--card-h override), but
   every text element above has its own low ceiling tuned for the tiny
   in-hand card size (e.g. the title tops out at 15px, the number circle at
   24px) — none of them were built to know this screen's card is 2-3x
   bigger. All re-tied to this screen's own (much larger) --card-w so they
   scale up together instead of staying pinned near their old caps. */
#referenceCardWrap .card-back .card-quote {
  display: -webkit-box;
  font-size: clamp(12px, calc(var(--card-w) * 0.055), 18px);
}

#referenceCardWrap .card-back .card-title {
  font-size: clamp(18px, calc(var(--card-w) * 0.095), 32px);
}

#referenceCardWrap .card-back .card-type {
  font-size: clamp(12px, calc(var(--card-w) * 0.055), 18px);
  padding-bottom: 5px;
}

#referenceCardWrap .card-back .card-testament {
  font-size: clamp(10px, calc(var(--card-w) * 0.045), 15px);
  padding-bottom: 10px;
}

#referenceCardWrap .card-back-number {
  font-size: clamp(22px, calc(var(--card-w) * 0.163), 42px);
}

#referenceCardWrap .card-back-chapters-value {
  font-size: clamp(13px, calc(var(--card-w) * 0.09), 21px);
}

#referenceCardWrap .card-back-chapters-label {
  font-size: clamp(7px, calc(var(--card-w) * 0.026), 10px);
}


/* .card-type's colour is set inline per-card (matches its category), so
   only weight/size live here. .card-testament is always grey, per spec.
   font-size tied to --card-w (not vh, unlike before) for the same reason
   as the chapters label fix above: these sit in a fixed-width box whose
   width follows the card's actual rendered width, not the viewport, so a
   vh-driven size stayed just as big on a narrow 5-across card as a wide
   one — forcing type/testament to wrap and squeeze the title out of its
   own space above them. */
.card-back .card-type,
.card-back .card-testament {
  font-size: clamp(6px, calc(var(--card-w) * 0.0815), 11px);
  font-weight: 300;
  text-transform: uppercase;
  padding-bottom: 5px;
}

.card-back .card-testament {
  color: var(--color-text-muted);
  font-weight: 500;
  text-transform: uppercase;
  font-size: clamp(5px, calc(var(--card-w) * 0.0667), 9px);
}

.card-back-chapters {
  position: absolute;
  left: 31%;
  right: 32%;
  top: 82%;
  bottom: 6.3%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
  line-height: 1.1;
}

/* Without this, the number alone ("50") reads as an unlabelled digit with
   no indication of what it's counting. */
.card-back-chapters-label {
  font-size: clamp(4px, calc(var(--card-w) * 0.026), 6px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0.9;
  /* Safety net on top of the --card-w fix above: this box is small enough
     that wrapping to 2 lines (13 characters is tight even at the right
     font size) would double the label's height and push the number below
     it outside the box — nowrap keeps it to one line even if the size
     ever ends up borderline again, rather than silently wrapping. */
  white-space: nowrap;
}

.card-back-chapters-value {
  /* Tied to --card-w for the same reason as .card-back-number above. */
  font-size: clamp(8px, calc(var(--card-w) * 0.09), 13px);
  font-weight: 700;
}

.card.correct .card-face {
  box-shadow: 0 0 0 3px var(--color-success), var(--shadow-sm);
}

.card.wrong .card-face {
  box-shadow: 0 0 0 3px var(--color-danger), var(--shadow-sm);
}

/* Complete mode skips the colored ring — the flip + sound already say
   correct/wrong, and the next card now appears right after the flip
   instead of pausing for a highlight to be seen (see handleLongInsert /
   resolveUnresolved in ui.js). Standard mode's round-reveal keeps the
   ring, since there it's the only per-card feedback and several cards are
   compared side by side. */
#screen-long .card.correct .card-face,
#screen-long .card.wrong .card-face {
  box-shadow: var(--shadow-sm);
}

/* Round-result badge — floats in the corner of the hand once cards are
   revealed, showing how many were correct (or a star for a perfect 5/5). */
.round-score-badge {
  position: absolute;
  top: -14px;
  right: -14px;
  min-width: 32px;
  height: 32px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-surface);
  font-weight: 800;
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  transform: scale(0.5);
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 10;
  pointer-events: none;
}

.round-score-badge.visible {
  opacity: 1;
  transform: scale(1);
}

.round-score-badge.perfect {
  font-size: 19px;
  background: var(--color-accent-dark);
}

/* ===================== Long mode line ===================== */

/* Wraps the placed-cards line and the pending card together so a mobile
   media query below can lay them out as one row (pending card left, in
   its own section) instead of two stacked rows — see the mobile-portrait
   override further down. Desktop keeps the original stacked arrangement
   (line on top, pending below), unaffected. */
.long-board {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  min-width: 0;
}

.long-line-wrap {
  overflow-x: auto;
  /* Horizontal padding is part of the scrollable range (not just visual
     spacing) — without it, scrolling all the way to either end puts the
     first/last card flush against the container's edge, making it hard to
     tell it's fully visible, or to drag past it to insert there. */
  padding: 8px 16px 14px;
  /* Without these, this flex child of .game-body (align-items: center)
     shrink-wraps to fit its ever-growing content instead of staying
     capped at the available width — so the whole PAGE scrolled
     horizontally instead of just this row, dragging the header and the
     pending card out of view with it. width + min-width:0 keeps it
     pinned to the real available width so overflow-x actually scrolls
     just the card row, leaving everything else fixed in place. */
  width: 100%;
  min-width: 0;
}

/* Cards are absolutely positioned (left computed in JS by layoutLongLine in
   ui.js) — same model as Standard mode's drag-reorder hand. No separate "+"
   slot elements: dragging the pending card over the row opens a gap by
   sliding neighbours aside, purely via each card's own `left`. Width/margin
   are also set in JS per render so the row centers itself while narrower
   than the visible area, and scrolls normally once it isn't. */
.long-line {
  position: relative;
  padding: 4px;
  /* In the mobile one-row layout, .long-line-wrap is itself display:flex
     (to sit beside the pending section) — without this, .long-line becomes
     a flex item there and the browser silently shrinks it to fit the
     available space, ignoring the explicit width layoutLongLine sets in
     JS. That undersized box then under-reserves the scrollable range for
     the trailing "insert after the last card" gap, leaving it not fully
     scrollable into view even at max scroll. */
  flex-shrink: 0;
}

.long-line .card {
  position: absolute;
  top: 0;
}

.long-pending-wrap {
  display: flex;
  justify-content: center;
  padding-top: 10px;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/* Dragging the pending card back over its own section "accepts" it as a
   deliberate put-it-back gesture (see isOverPendingWrap in ui.js) — the
   ring + slight grow gives that a visible reaction distinct from the
   section's own resting look, including on mobile where it's already
   tinted (see the breakpoint overrides below), where the tint alone
   wouldn't otherwise change. */
.long-pending-wrap.pending-drop-active {
  transform: scale(1.05);
  box-shadow: 0 0 0 3px var(--color-accent);
}

/* ===================== Result screen ===================== */

.result-content {
  margin: auto;
  width: 100%;
  max-width: 420px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.result-title {
  font-size: 30px;
  color: var(--color-accent-dark);
}

.result-stats {
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 16px 20px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.result-row {
  display: flex;
  justify-content: space-between;
  font-size: 15px;
}

.result-label { color: var(--color-text-muted); }
.result-value { font-weight: 700; }

.result-celebration {
  font-weight: 700;
  color: var(--color-accent-dark);
  font-size: 16px;
}

.result-buttons {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.result-save-row {
  display: flex;
  justify-content: center;
}

.result-saved-confirm {
  text-align: center;
  font-weight: 700;
  color: var(--color-accent-dark);
  font-size: 14px;
}

/* ===================== Panels (High scores / Options) ===================== */

.panel {
  margin: auto;
  width: 100%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.panel-title {
  text-align: center;
  font-size: 26px;
  color: var(--color-accent-dark);
}

/* Visually set apart from the fields/buttons above it (top border, its own
   padding) so a destructive, irreversible action doesn't just look like
   the next item in the same list. */
.options-danger-zone {
  display: flex;
  padding-top: 16px;
  border-top: 1px solid var(--color-border);
}

.options-danger-zone .btn { width: 100%; }

/* ===================== About screen ===================== */

.about-section {
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  box-shadow: var(--shadow-sm);
  text-align: left;
}

.about-section-title {
  font-size: 16px;
  color: var(--color-accent-dark);
  margin-bottom: 6px;
}

.about-section p {
  color: var(--color-text);
  line-height: 1.5;
  font-size: 14px;
}

.about-section a {
  color: var(--color-accent-dark);
  font-weight: 600;
}

.about-copyright {
  margin-top: 8px;
  font-size: 12px;
  color: var(--color-text-muted);
}

.tabs {
  display: flex;
  gap: 8px;
  background: var(--color-bg-alt);
  padding: 4px;
  border-radius: var(--radius-md);
}

.tab {
  flex: 1;
  border: none;
  background: transparent;
  padding: 10px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  color: var(--color-text-muted);
}

.tab.active {
  background: var(--color-surface);
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
}

.table-wrap {
  background: var(--color-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 8px 4px;
  min-height: 120px;
}

.scores-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.scores-table th {
  text-align: left;
  color: var(--color-text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 8px 10px;
}

.scores-table td {
  padding: 10px;
  border-top: 1px solid var(--color-border);
}

.scores-table tr:first-child td { font-weight: 700; color: var(--color-accent-dark); }

.empty-state {
  text-align: center;
  color: var(--color-text-muted);
  padding: 24px 12px;
  font-size: 14px;
}

/* ===================== Reference / browse screen ===================== */

/* Wider than other panels — the "view cards" tab's single card looks fine
   just centred with extra side space, but the "full context" chart's
   4-column grid needs the room to keep each column legible. */
.reference-panel {
  max-width: 900px;
}

.reference-tab-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.reference-overview {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.reference-testament {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.reference-testament-header {
  background: var(--color-accent-dark);
  color: var(--color-surface);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  /* Fluid rather than fixed — "Det Gamle Testamente"/"Det Gamle
     Testamente" runs longer than "Old Testament"/"Gamla Testamentet", and
     future translations will vary further still. Scales down only on
     narrow viewports where it'd otherwise risk wrapping to 2 lines;
     unchanged (15px) from ~420px wide up, so this doesn't affect how it
     already looked on anything but the narrowest phones. */
  font-size: clamp(12px, 3.6vw, 15px);
}

/* column-count (rather than CSS grid) lets sections of very different
   length — "Historiska böcker" (12 books) next to "Lagen" (5 books) —
   flow and balance naturally down each column instead of being forced
   into equal-height grid rows. break-inside:avoid on .reference-section
   keeps a whole category together instead of splitting across columns. */
.reference-section-grid {
  column-count: 4;
  column-gap: 16px;
}

.reference-section {
  break-inside: avoid;
  margin-bottom: 16px;
  background: var(--color-surface);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.reference-section-header {
  color: #fff;
  font-weight: 700;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding: 8px 10px;
}

.reference-section-list {
  margin: 0;
  padding: 8px 10px 8px 26px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
}

.reference-section-list li {
  margin-bottom: 4px;
}

.reference-section-list li::marker {
  font-weight: 700;
}

/* Sized much bigger than the in-game --card-w/--card-h (which are tuned for
   fitting 5-across or a single card next to the placed line) — this is the
   one context where a card is the ONLY thing on screen and the point is to
   read it comfortably, not fit it alongside anything else. Height was
   purely vw-driven, which ignored viewport HEIGHT entirely — on a mobile
   phone held sideways (wide but short), that let the card grow far taller
   than the screen itself. min(...,92vh) caps it against the actual
   available height too (92, not 100, to leave a little room for the
   title/tabs/nav around it). Width is derived from height via the fixed
   210:135 ratio (see CARD_ASPECT_RATIO in ui.js) instead of its own
   independent clamp, so capping height by viewport can't leave the two
   dimensions out of proportion with each other. */
#screen-reference {
  --card-h: clamp(280px, min(93vw, 92vh), 498px);
  --card-w: calc(var(--card-h) * 135 / 210);
}

.reference-card-wrap {
  display: flex;
  justify-content: center;
  padding: 12px 0;
}

.reference-card-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
}

.reference-card-counter {
  font-weight: 600;
  color: var(--color-text-muted);
  min-width: 64px;
  text-align: center;
}

/* ===================== Options fields ===================== */

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  box-shadow: var(--shadow-sm);
}

.field-label {
  font-size: 13px;
  color: var(--color-text-muted);
  font-weight: 600;
}

.field input[type="text"],
.field select {
  font-family: inherit;
  font-size: 16px;
  border: none;
  background: transparent;
  color: var(--color-text);
  padding: 4px 0;
  outline: none;
}

.field select:disabled,
.field option:disabled { color: var(--color-text-muted); }

.field-row {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
}

/* Toggle switch */
.toggle { display: inline-flex; align-items: center; }
.toggle input { position: absolute; opacity: 0; width: 44px; height: 26px; margin: 0; cursor: pointer; }
.toggle-track {
  width: 44px;
  height: 26px;
  border-radius: 999px;
  background: var(--color-border);
  position: relative;
  transition: background 0.2s ease;
  display: block;
}
.toggle-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s ease;
}
.toggle input:checked + .toggle-track { background: var(--color-accent); }
.toggle input:checked + .toggle-track .toggle-thumb { transform: translateX(18px); }

/* ===================== Overlays / Dialogs ===================== */

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(58, 50, 38, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}

.dialog {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  padding: 24px 22px;
  max-width: 380px;
  width: 100%;
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.dialog h3 { font-size: 19px; color: var(--color-accent-dark); }
.dialog p { color: var(--color-text-muted); font-size: 14px; line-height: 1.4; }

/* installInstructionsBody (see index.html) holds two <p> steps set via
   innerHTML — its own flex+gap since .dialog's gap only reaches direct
   children, not these nested paragraphs. */
#installInstructionsBody {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.install-instructions-icon {
  width: 18px;
  height: 18px;
  vertical-align: -4px;
  margin: 0 1px;
}

.dialog-input {
  font-family: inherit;
  font-size: 16px;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text);
  padding: 10px 12px;
  outline: none;
}

.dialog-input:focus { border-color: var(--color-accent); }

.dialog-buttons {
  display: flex;
  gap: 10px;
  margin-top: 4px;
}

.dialog-buttons .btn { flex: 1; }

/* ===================== Responsive ===================== */

@media (min-width: 640px) {
  .screen { padding: 32px 24px; }
}

/* Narrow screens (either orientation — unlike the portrait-only card-size
   query below, a narrow phone's reference chart columns need to shrink
   whether the phone is upright or sideways): 4 columns of book titles get
   unreadably thin, so drop to 2. */
@media (max-width: 640px) {
  .reference-section-grid { column-count: 2; }
}

/* Narrow portrait viewports (mobile held upright) — the base --card-w/h
   above are driven purely by viewport HEIGHT (so landscape, the originally
   intended orientation, gets large cards), which means on a tall narrow
   phone they max out well short of the available width, leaving large
   unused side margins. Scoped to portrait only so it never fights with the
   landscape override below. */
@media (max-width: 640px) and (orientation: portrait) {
  :root {
    --card-w: clamp(85px, 42vw, 190px);
    --card-h: clamp(130px, 65vw, 300px);
  }
  /* Reclaims a few more px of width for Standard mode's 5-across row —
     every pixel counts when dividing a ~375px screen five ways. */
  .screen { padding: 16px 8px calc(16px + env(safe-area-inset-bottom)); }
  /* .game-body centers vertically by default, which is fine when its
     content roughly fills the space below the header — but on a tall
     phone the leftover space is huge, so centering reads as a big empty
     gap between the header and the cards. Packing from the top keeps the
     header and cards close together instead. */
  .game-body { justify-content: flex-start; gap: 14px; padding-top: 4px; }
  .game-header { margin-bottom: 6px; }

  /* Long mode only: two stacked rows (placed-cards line, then the pending
     card below) each have to share the available height, capping how tall
     either can be. Restructured as one row instead — the pending card
     gets its own tinted, bordered section on the left (so it's obviously
     "the card being placed" vs. the already-revealed ones), with the
     placed-cards line scrolling horizontally to its right. One row means
     the card height is no longer split between two — noticeably bigger.
     Desktop is unaffected (this query only matches narrow portrait
     screens) and keeps the original two-row stacked layout. */
  /* Width was purely height-driven (33vh), which ignored that this row is
     split between the pending section and the scrolling line — on a tall
     narrow phone that produced a card wider than the line-wrap's own
     visible width, so no scroll position could ever show a whole card,
     least of all the last one. min(...,34vw) caps it against the actual
     screen width too. Height is now derived from the (already width-aware)
     card width via the fixed aspect ratio, instead of its own independent
     vh clamp, so the two can't drift out of proportion with each other. */
  #screen-long {
    --card-w: clamp(80px, min(33vh, 34vw), 170px);
    --card-h: calc(var(--card-w) * 210 / 135);
  }
  #screen-long .long-board {
    flex-direction: row;
    align-items: stretch;
    flex: 1;
    min-height: 0;
  }
  #screen-long .long-pending-wrap {
    order: -1;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px 14px;
    background: var(--color-accent-soft);
    border-right: 2px solid var(--color-accent);
    border-radius: var(--radius-md) 0 0 var(--radius-md);
    /* The pending card becomes position:fixed while being dragged (it
       leaves normal flow entirely), which would otherwise let this
       flex:0 0 auto box collapse down to just its own padding right when
       a player is trying to drag back onto it — pinning a floor here
       keeps the "put it back" target the same size whether or not the
       card inside is actually still in flow. */
    min-width: calc(var(--card-w) + 28px);
    min-height: calc(var(--card-h) + 20px);
  }
  #screen-long .long-line-wrap {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    /* Right padding widened so the last card clears the screen edge fully
       when scrolled all the way over — same reasoning as the base rule. */
    padding: 8px 18px 8px 14px;
  }

  /* Welcome screen: five buttons stacked in one column ran the whole
     screen tall — grouped into two rows instead (2 primary side by side,
     then the 3 secondary side by side), matching the landscape grouping
     further down. Also trims the logo's own gap, which was tuned for a
     tall single-column stack and left a big empty band above the buttons
     otherwise. */
  .welcome-content { gap: 14px; }
  .app-title-wrap { margin-bottom: 0; }
  /* Narrower on mobile specifically — reclaims a bit of the vertical
     rhythm the two-row button grouping above needs. Doesn't widen the
     secondary buttons below (they're sized off the screen width, not the
     logo — separate flex siblings in the same column), so the icon/font
     shrink further down is what actually makes long words like
     "Inställningar" fit. */
  .app-logo { max-width: 80%; }
  .welcome-buttons-primary {
    flex-direction: row;
    gap: 10px;
  }
  .welcome-buttons-primary .btn-two-line {
    flex: 1;
    padding: 12px 8px 14px;
  }
  .welcome-buttons-primary .btn-title { font-size: 15px; }
  .welcome-buttons-primary .btn-subtitle { font-size: 11px; }
  .welcome-buttons-secondary {
    flex-direction: row;
    gap: 8px;
  }
  .welcome-buttons-secondary .btn {
    flex: 1;
    padding: 10px 6px;
    font-size: 12px;
  }
  /* Fallback for when the row is still too tight even after the logo and
     base font shrink above — a smaller icon and tighter icon-to-label gap
     claim back a few more px for the text itself. */
  .welcome-buttons-secondary .btn-icon-prefix { width: 16px; height: 16px; }
  .welcome-buttons-secondary .btn-icon-label {
    gap: 6px;
  }
}

/* Short landscape viewports (mobile in landscape) — tighten vertical rhythm
   so everything fits without scrolling. */
@media (orientation: landscape) and (max-height: 500px) {
  :root {
    /* The old bounds here (104-150 / 65-100) had their vh-scaling term
       tuned too low: 14vh/25vh only clears the floor above ~465px of
       viewport height, so on virtually every real landscape phone
       (height 350-430px) the clamp just silently returned its minimum —
       pinning cards to 65px wide regardless of how much width was
       actually free to use. Rebalanced so the vh term is the one that
       actually applies across the realistic phone-landscape height range. */
    --card-h: clamp(120px, 45vh, 250px);
    --card-w: clamp(80px, 29vh, 160px);
  }
  .screen { padding: 10px 16px; }
  .game-header { margin-bottom: 4px; }
  .game-header-stats { padding: 6px 14px; }
  .game-body { gap: 8px; }
  .game-instructions { font-size: 12px; }
  .welcome-content, .result-content { gap: 14px; }
  .app-logo { max-width: 1080px; }
  /* Testament is the least essential line — drop it first when a card is too
     short to fit everything, keeping title/number/type legible. Quote is
     already hidden by default everywhere (see .card-back .card-quote). */
  .card-back .card-testament { display: none; }
  .card-face { padding: 6px 5px; }
  .card-back-top { gap: 0; }

  /* Long mode: the two-row stacked layout (placed-cards line above,
     pending card below) no longer fits a short landscape screen once
     --card-h above got bigger — same fix as the mobile-portrait query:
     one row instead, pending card in its own tinted section on the left,
     placed-cards line scrolling to its right. */
  #screen-long .long-board {
    flex-direction: row;
    align-items: stretch;
    flex: 1;
    min-height: 0;
  }
  #screen-long .long-pending-wrap {
    order: -1;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 10px;
    background: var(--color-accent-soft);
    border-right: 2px solid var(--color-accent);
    border-radius: var(--radius-md) 0 0 var(--radius-md);
    /* See the matching rule in the portrait breakpoint above — without a
       floor here, this flex:0 0 auto box collapses to just its own padding
       once the dragged card leaves flow (position:fixed), shrinking the
       "put it back" target right when it needs to be reliable. */
    min-width: calc(var(--card-w) + 20px);
    min-height: calc(var(--card-h) + 12px);
  }
  #screen-long .long-line-wrap {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    /* Right padding widened so the last card clears the screen edge fully
       when scrolled all the way over — same reasoning as the base rule. */
    padding: 4px 16px 4px 10px;
  }

  /* Mobile-landscape welcome screen: logo fills the left half, the buttons
     form two rows on the right (2 primary, then 3 secondary) — a single
     column of five would push the bottom buttons off a short landscape
     screen entirely. */
  .welcome-content {
    flex-direction: row;
    align-items: center;
    max-width: 640px;
  }
  /* flex-grow:0 on the title (vs. buttons' :1) so it never eats into the
     buttons' share when there's spare row width — with both set to grow:1
     before, the browser split any extra space 50/50 regardless of these
     basis percentages, which is why the two ended up looking equal-width
     instead of 40/60. */
  .app-title-wrap { flex: 0 1 40%; margin-bottom: 0; }
  .app-logo { width: 100%; }
  /* This column is narrow here, same proportions as the mobile-portrait
     case — the picture's <source> below switches to logo-bg-short.png in
     this same condition, so match its (short-asset) text padding too. */
  .app-logo-text {
    left: 15.65%;
    right: 12.04%;
    font-size: 10.6cqw;
  }
  .welcome-buttons {
    flex: 1 1 60%;
    gap: 8px;
  }
  .welcome-buttons-primary,
  .welcome-buttons-secondary {
    flex-direction: row;
    gap: 8px;
  }
  .welcome-buttons-primary .btn-two-line,
  .welcome-buttons-secondary .btn {
    flex: 1;
  }
  .btn-two-line { padding: 8px 6px 10px; }
  .btn-title { font-size: 13px; }
  .btn-subtitle { font-size: 10px; }
  .welcome-buttons-secondary .btn { padding: 8px 6px; font-size: 11px; }
}
