:root {
  --bg: #f6f3ee;
  --surface: #ffffff;
  --surface-2: #f0ebe4;
  --text: #1d1b19;
  --muted: #6b6560;
  --border: #e3dcd2;
  --primary: #ff6b35;
  --primary-hover: #f05a22;
  --primary-text: #ffffff;
  --relaxed: #2f9e63;
  --firm: #7a4fc2;
  --strict: #3567d4;
  --ragebait: #d93a2f;
  --error: #c62828;
  --error-text: #ffffff; /* text on a filled --error button */
  --level-1: #f2c94c;
  --level-2: #f2a93b;
  --level-3: #ee8434;
  --level-4: #e2592e;
  --level-5: #c9302c;
  --radius: 16px;
  --shadow: 0 4px 18px rgba(40, 30, 20, 0.08);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #17161b;
    --surface: #222027;
    --surface-2: #2b2832;
    --text: #f2efe9;
    --muted: #a7a19a;
    --border: #3a3641;
    --primary: #ff7a45;
    --primary-hover: #ff8e5f;
    --error: #ff6b6b;
    --error-text: #17161b; /* white on the lighter red would be too faint */
    --shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
    color-scheme: dark;
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

[hidden] {
  display: none !important;
}

h1,
h2 {
  line-height: 1.2;
  margin: 0 0 12px;
}

h1 {
  font-size: 1.9rem;
}

h2 {
  font-size: 1.1rem;
}

.muted {
  color: var(--muted);
}

.error {
  color: var(--error);
  font-weight: 600;
  margin: 8px 0 0;
}

/* "Your browser isn't letting this site save data": under the setup header, and on the history
   page in place of the empty state. Same red line as the other errors, with the space of a card. */
.storage-warning {
  margin: 0 0 24px;
}

.app {
  max-width: 600px;
  margin: 0 auto;
  padding: 24px 16px 40px;
}

.app-header {
  text-align: center;
  margin-bottom: 24px;
}

.app-header p {
  margin: 0;
}

.step {
  margin-bottom: 28px;
}

/* Start without a character scrolls to step 1, and a Quick start tap that corrected the Custom
   field to step 3 (onStartClick); keep a little space above the heading. */
#characterStep,
#durationStep {
  scroll-margin-top: 16px;
}

#characterError {
  margin: 0 0 12px;
}

/* ---------- buttons ---------- */

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.btn {
  border: 1.5px solid var(--border);
  background: var(--surface);
  border-radius: 12px;
  padding: 12px 18px;
  font-weight: 600;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}

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

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

.btn.primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-text);
}

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

.btn.big {
  display: block;
  width: 100%;
  padding: 16px;
  font-size: 1.15rem;
}

.btn.wide {
  display: block;
  width: 100%;
}

/* Destructive (Delete in the history page's delete dialog). */
.btn.danger {
  background: var(--error);
  border-color: var(--error);
  color: var(--error-text);
}

.btn.danger:hover {
  filter: brightness(0.92);
}

/* A smaller button that is still a 44x44px tap target (Edit / Done and Delete on the history page). */
.btn.compact {
  min-height: 44px;
  min-width: 44px;
  padding: 8px 14px;
}

button:focus-visible,
input:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
}

.icon-btn {
  border: none;
  background: none;
  font-size: 1.4rem;
  line-height: 1;
  padding: 4px 8px;
  color: var(--muted);
}

/* Links and text buttons that stand on their own (not inside a sentence): a 44px tall tap
   target, with the text where it would be anyway. */
.back-link,
.header-link a,
.text-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* "Privacy" under Start session and at the bottom of history.html: small and grey, but still a
   44x44px tap target. --muted is at least 4.5:1 on --bg in light and dark mode. */
.page-footer {
  margin: 16px 0 0;
  text-align: center;
}

.footer-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 0 8px;
  font-size: 0.85rem;
  color: var(--muted);
}

/* ---------- setup: characters ---------- */

/* minmax(0, 1fr): with large text (200%) at 320px, a long word wraps inside its card instead of
   making the grid wider than the screen. */
.character-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.char-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 10px;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  text-align: center;
  box-shadow: var(--shadow);
  transition: border-color 0.15s, transform 0.1s;
}

.char-card img {
  width: 96px;
  max-width: 100%;
  height: auto;
}

.char-card {
  min-width: 0;
  overflow-wrap: anywhere;
}

.char-card[aria-pressed="true"] {
  border-color: var(--primary);
  background: color-mix(in srgb, var(--primary) 8%, var(--surface));
}

.char-card:active {
  transform: scale(0.98);
}

.char-name {
  font-weight: 700;
  font-size: 1.05rem;
}

.char-tagline {
  font-size: 0.85rem;
  color: var(--muted);
}

.badge {
  font-size: 0.75rem;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 999px;
  color: #fff;
}

.badge-relaxed {
  background: var(--relaxed);
}

.badge-firm {
  background: var(--firm);
}

.badge-strict {
  background: var(--strict);
}

.badge-ragebait {
  background: var(--ragebait);
}

/* "Create your own" (always the last card of the main grid) and "Your characters" below it.
   A custom card is a frame holding the select button (a .char-card without its own border) and
   the Edit / Delete row: a button can't contain other buttons. */
.create-card img {
  opacity: 0.9;
}

.create-card[aria-disabled="true"] {
  cursor: default;
  box-shadow: none;
}

.create-card[aria-disabled="true"]:active {
  transform: none;
}

.badge-free {
  background: var(--primary);
  color: var(--primary-text);
}

.custom-section {
  margin-top: 24px;
}

.custom-section h3 {
  font-size: 1.05rem;
  margin: 0 0 12px;
}

.custom-item {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  min-width: 0;
  transition: border-color 0.15s;
}

.custom-item.selected {
  border-color: var(--primary);
  background: color-mix(in srgb, var(--primary) 8%, var(--surface));
}

.custom-item .char-card {
  flex: 1;
  border: none;
  box-shadow: none;
  background: transparent;
  border-radius: var(--radius) var(--radius) 0 0;
  padding-bottom: 6px;
}

/* The name is the user's own text: long words break instead of widening the card. */
.custom-item .char-name {
  overflow-wrap: anywhere;
}

.custom-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  padding: 0 8px 10px;
}

.custom-actions .btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  color: var(--text);
  font-size: 0.9rem;
}

/* ---------- setup: choices ---------- */

.choice-group {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.choice {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px;
  text-align: left;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: var(--radius);
}

.choice span {
  font-size: 0.85rem;
  color: var(--muted);
}

.choice[aria-pressed="true"] {
  border-color: var(--primary);
  background: color-mix(in srgb, var(--primary) 8%, var(--surface));
}

/* ---------- duration picker ---------- */

/* 8 presets: always 2 even rows of 4, on setup and in the Start over dialog. */
.chips {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}

.chip {
  min-height: 44px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 6px 4px;
  font-weight: 600;
  white-space: nowrap;
}

.chip[aria-pressed="true"] {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-text);
}

.custom-minutes {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
}

.custom-minutes input {
  width: 80px;
  min-height: 44px;
  padding: 8px 10px;
  border: 1.5px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
}

/* "Max. 240 min." etc. under the custom field: no height while empty, so it takes no space
   until the field was corrected. Same size as the setting hints. */
.custom-note {
  margin: 0;
  font-size: 0.85rem;
}

.custom-note:not(:empty) {
  margin-top: 6px;
}

/* ---------- session ---------- */

.session-info {
  text-align: center;
  font-size: 0.9rem;
  margin: 0 0 8px;
  text-wrap: balance; /* if it wraps, two even lines instead of "min" alone */
}

/* In the page flow (not on top), so it never covers the character, timer or buttons. */
.screen-note {
  text-align: center;
  font-size: 0.85rem;
  margin: -4px 0 8px;
  text-wrap: balance;
}

.stage {
  display: flex;
  justify-content: center;
  --mult: 1;
}

.stage.ragebait {
  --mult: 2.2;
}

.char-img {
  width: min(230px, 60vw);
  height: auto;
  transform-origin: 50% 100%;
  animation: breathe 4.2s ease-in-out infinite;
}

@keyframes breathe {
  0%,
  100% {
    transform: scale(1, 1);
  }
  50% {
    transform: scale(1.012, 1.028);
  }
}

/* Kind hops, firm leans in slowly (never shakes), strict shakes, ragebait does a cheeky head tilt.
   Ragebait's --mult makes it bigger. */
.stage.react-1 { --amp: 3px; --tilt: 1deg; }
.stage.react-2 { --amp: 5px; --tilt: 2deg; }
.stage.react-3 { --amp: 8px; --tilt: 3deg; }
.stage.react-4 { --amp: 11px; --tilt: 4deg; }
.stage.react-5 { --amp: 15px; --tilt: 5deg; }

.stage.strict.react-1,
.stage.strict.react-2 {
  animation: shake 0.5s ease-in-out 2;
}

.stage.strict.react-3,
.stage.strict.react-4,
.stage.strict.react-5 {
  animation: shake 0.4s ease-in-out 4;
}

/* Firm: one slow, calm lean. Higher levels lean a bit further and hold it a bit longer. */
.stage.firm.react-1,
.stage.firm.react-2 {
  animation: lean 1s ease-in-out 1;
}

.stage.firm.react-3,
.stage.firm.react-4,
.stage.firm.react-5 {
  animation: lean 1.6s ease-in-out 1;
}

.stage.kind.react-1,
.stage.kind.react-2,
.stage.kind.react-3,
.stage.kind.react-4,
.stage.kind.react-5 {
  animation: hop 0.6s ease-out 2;
}

.stage.ragebait.react-1,
.stage.ragebait.react-2,
.stage.ragebait.react-3,
.stage.ragebait.react-4,
.stage.ragebait.react-5 {
  transform-origin: 50% 100%;
  animation: taunt 0.7s ease-in-out 3;
}

.stage.react-good {
  --amp: 10px;
  animation: hop 0.7s ease-out 2;
}

/* Firm approves with one small nod, more restrained than kind's hop. */
.stage.firm.react-good {
  --amp: 4px;
  animation: nod 0.9s ease-in-out 1;
}

/* Ragebait isn't proud when you do well: just a small, unimpressed shrug. */
.stage.ragebait.react-good {
  --amp: 3px;
  animation: shrug 1s ease-in-out 1;
}

/* After every distraction reaction: "OK, back to work". One gentle nod for every
   personality, never a shake. */
.stage.react-refocus {
  --amp: 4px;
  animation: nod 0.9s ease-in-out 1;
}

@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(calc(var(--amp) * var(--mult) * -1)) rotate(calc(var(--mult) * -1deg));
  }
  75% {
    transform: translateX(calc(var(--amp) * var(--mult))) rotate(calc(var(--mult) * 1deg));
  }
}

@keyframes taunt {
  0%,
  100% {
    transform: rotate(0);
  }
  25% {
    transform: rotate(calc(var(--tilt) * var(--mult) * -1)) translateY(calc(var(--amp) * -0.5));
  }
  75% {
    transform: rotate(calc(var(--tilt) * var(--mult))) translateY(calc(var(--amp) * -0.5));
  }
}

@keyframes lean {
  0%,
  100% {
    transform: translateY(0) scale(1);
  }
  35%,
  70% {
    transform: translateY(calc(var(--amp) * 0.6)) scale(1.02);
  }
}

@keyframes nod {
  0%,
  100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(var(--amp));
  }
}

@keyframes shrug {
  0%,
  100% {
    transform: translateY(0);
  }
  30%,
  60% {
    transform: translateY(calc(var(--amp) * -1));
  }
}

@keyframes hop {
  0%,
  100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(calc(var(--amp) * var(--mult) * -1.6));
  }
}

.timer-block {
  text-align: center;
  margin: 12px 0 20px;
}

.timer {
  font-size: clamp(2.8rem, 14vw, 4rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.progress {
  height: 10px;
  background: var(--surface-2);
  border-radius: 999px;
  overflow: hidden;
}

.progress-bar {
  height: 100%;
  width: 0;
  background: var(--primary);
  border-radius: 999px;
  transition: width 0.5s linear;
}

.distraction h2 {
  text-align: center;
}

.distraction-buttons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 8px;
}

.distraction-buttons.advanced {
  grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
}

.btn.level {
  border-width: 2px;
  padding: 12px 8px;
}

/* Simple: always two full rows, 3 + 2. On a 6-column grid the first three buttons span 2 columns,
   the last two span 3. Less side padding, so "Lost track" stays on one line on 320px phones. If a
   label still wraps (a large phone font), every row grows to the same height. */
.distraction-buttons.simple {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-auto-rows: 1fr;
}

.distraction-buttons.simple .btn.level {
  grid-column: span 2;
  padding: 12px 4px;
}

.distraction-buttons.simple .btn.level:nth-child(n + 4) {
  grid-column: span 3;
}

/* Advanced labels are short: keep "10+ min" on one line in a 4-column row on 360px phones. */
.distraction-buttons.advanced .btn.level {
  padding: 12px 4px;
  white-space: nowrap;
}

.btn.level-1 { border-color: var(--level-1); }
.btn.level-2 { border-color: var(--level-2); }
.btn.level-3 { border-color: var(--level-3); }
.btn.level-4 { border-color: var(--level-4); }
.btn.level-5 { border-color: var(--level-5); }

.btn.level:hover {
  background: var(--surface-2);
}

/* Advanced: a length longer than the free time so far (updateLengthButtons in app.js).
   Greyed out but still readable, and the same size, so nothing moves. */
.btn.level:disabled {
  opacity: 1;
  color: var(--muted);
  border-color: var(--border);
  background: var(--surface-2);
  cursor: not-allowed;
  transform: none;
}

/* ---------- distraction category picker ---------- */

/* Spans both columns of the sticky session bar, above Motivate me / End session. */
.category-picker {
  grid-column: 1 / -1;
  padding: 4px 12px 12px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  overflow: hidden;
}

/* The question on the left, Skip on the right, on one row (Skip sets its height). */
.category-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 0 -8px 4px 0;
}

.category-prompt {
  margin: 0;
  font-weight: 600;
}

/* Secondary to the categories: plain grey text, no border or fill, but still a
   44px tap target. --muted is at least 4.5:1 on --surface (and on --surface-2 when
   hovered) in light and dark mode. */
.skip-btn {
  flex: none;
  min-width: 64px;
  min-height: 44px;
  padding: 8px 12px;
  border: none;
  border-radius: 10px;
  background: none;
  color: var(--muted);
  font-weight: 600;
}

.skip-btn:hover {
  background: var(--surface-2);
}

.category-buttons {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

/* Big enough to tap comfortably on a phone. */
.category-buttons .btn {
  min-height: 44px;
  padding: 8px;
}

.category-buttons .btn:hover {
  background: var(--surface-2);
}

/* ---------- undo ---------- */

/* Sits in Motivate me's cell while it's shown. The seconds left (" · 5" … " · 1", updated in
   app.js) are part of its label, not a bar, so they can't be read as a time limit on the
   category picker above it; then Motivate me comes back. */
.undo-btn {
  border-color: var(--primary);
}

.undo-btn:hover {
  border-color: var(--primary-hover);
}

/* Every digit the same width, so the label doesn't wobble as it counts down. */
.undo-seconds {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.motivation-card {
  position: relative;
  margin-top: 20px;
  padding: 16px 44px 16px 16px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.motivation-card p {
  margin: 8px 0 0;
}

/* A 44px tap target in the card's right padding (so it never covers the text), with the ×
   about where a smaller button would put it. */
.motivation-card .icon-btn {
  position: absolute;
  top: 2px;
  right: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
}

.motivation-badge {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--primary);
}

.motivation-badge[data-type="fact"] {
  color: var(--strict);
}

/* Always visible at the bottom of the screen while a session runs. */
.session-bar {
  position: sticky;
  bottom: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 24px -16px 0;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(6px);
}

/* ---------- summary ---------- */

#summaryScreen {
  text-align: center;
  padding-top: 16px;
}

.summary-title {
  margin-top: 16px;
}

.summary-percent {
  font-size: 3rem;
  font-weight: 800;
  color: var(--primary);
  margin: 0;
}

.summary-details {
  margin-bottom: 28px;
}

.summary-text {
  color: var(--muted);
  margin: 8px 0 0;
}

.summary-text.error {
  color: var(--error); /* "Couldn't save this session" */
}

/* ---------- open in another tab ---------- */

#elsewhereScreen {
  text-align: center;
  padding-top: 48px;
}

.elsewhere-title {
  font-size: 1.4rem;
}

#elsewhereScreen p {
  margin: 0 0 28px;
}

/* ---------- dialogs ---------- */

dialog {
  width: min(440px, calc(100vw - 32px));
  border: none;
  border-radius: var(--radius);
  padding: 24px;
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}

dialog::backdrop {
  background: rgba(20, 15, 10, 0.5);
}

dialog p {
  margin: 0 0 16px;
}

/* ---------- time away card ---------- */

/* At the bottom of the screen, over a lighter backdrop, so the character (held in its level1
   pose) and the timer stay visible above it. */
.away-dialog {
  margin: auto auto calc(16px + env(safe-area-inset-bottom));
}

.away-dialog::backdrop {
  background: rgba(20, 15, 10, 0.3);
}

.away-dialog h2 {
  margin-top: 0;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 10px;
}

/* Full-width buttons on top of each other, the primary one first (the continue/restart dialog). */
.dialog-stack {
  display: grid;
  gap: 10px;
}

#restartDuration {
  margin-bottom: 14px;
}

/* Checkbox with its label: long text wraps under itself, never under the box (fits 360px). */
.check-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 14px;
  cursor: pointer;
}

.check-row input {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin: 1px 0 0;
  accent-color: var(--primary);
}

.check-row span {
  min-width: 0;
}

/* Dialogs: the "save to history" checkboxes in the continue/restart and End session dialogs. */
dialog .check-row {
  min-height: 44px;
  align-items: center;
}

/* Setup screen: sound / screen-on checkboxes, with the Test sound button beside the first one. */
.session-settings .check-row {
  margin-bottom: 0;
}

.session-settings > .check-row,
.setting-row {
  min-height: 44px;
  align-items: center;
}

.setting-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.btn.test-sound {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 7px 12px;
  font-size: 0.85rem;
}

/* Lined up with the checkbox text: checkbox width + gap. */
.setting-hint {
  margin: 0 0 6px 30px;
  font-size: 0.85rem;
}

/* ---------- stats page ---------- */

.stats-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  margin-bottom: 16px;
}

.stats-table th,
.stats-table td {
  padding: 12px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

.stats-table th:not(:first-child),
.stats-table td:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.stats-table tbody tr:last-child td {
  border-bottom: none;
}

a {
  color: var(--primary);
}

.header-link {
  margin-top: 0 !important;
  font-weight: 600;
}

.tip-card {
  margin-bottom: 28px;
  padding: 16px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.tip-card p {
  margin: 0 0 10px;
}

.tip-card .btn {
  margin-top: 4px;
}

/* "Quick start" card under the header (updateQuickStart in app.js). The image box has a fixed
   size before the image loads, so nothing moves; any artwork fits inside it (object-fit). */
.quick-start {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 28px;
  padding: 12px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.quick-start-img {
  flex: none;
  width: 56px;
  aspect-ratio: 200 / 240;
  object-fit: contain;
}

.quick-start-text {
  flex: 1;
  min-width: 0;
}

.quick-start-text p {
  margin: 0;
}

.quick-start-label {
  font-size: 0.85rem;
}

.quick-start-line {
  font-weight: 700;
  font-size: 0.95rem;
}

/* Less side padding than .btn, so the line has room on a 320px screen. Still 44x44px or more. */
.quick-start-btn {
  flex: none;
  min-height: 44px;
  min-width: 44px;
  padding: 10px 14px;
}

/* "Change ↓" under the line: .footer-link on a <button> (it scrolls, it doesn't go anywhere), so no
   button look, underlined like the link. The negative margin cancels .footer-link's side padding,
   so the word lines up with the text above it. */
.quick-start-change {
  margin-left: -8px;
  border: none;
  background: none;
  text-decoration: underline;
}

/* "How it works" in the header: a button (it opens the card, it doesn't go anywhere) that looks
   like the "Your history" link next to it. */
.text-btn {
  border: none;
  background: none;
  padding: 0 2px;
  font-weight: 600;
  color: var(--primary);
  text-decoration: underline;
}

.header-sep {
  margin: 0 8px;
  color: var(--muted);
}

/* Opened from the header button (openHowItWorks): keep a little space above the card. */
.how-it-works {
  scroll-margin-top: 16px;
}

.how-it-works ul {
  margin: 0 0 10px;
  padding-left: 1.2em;
}

.how-it-works li + li {
  margin-top: 8px;
}

/* The heading only gets focus from the script, to be read out; it isn't something to press. */
.how-it-works h2:focus {
  outline: none;
}

/* Same for these: focus goes there from the script so a screen reader reads them (app.js). */
#sessionInfo:focus,
#distractionPrompt:focus,
#summaryTitle:focus,
#characterStepTitle:focus,
#restartStep2Title:focus,
#elsewhereTitle:focus {
  outline: none;
}

/* Read by screen readers, invisible and taking no space on screen (the live region in index.html). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.link-btn {
  margin-top: 10px;
  text-align: center;
  text-decoration: none;
  color: var(--text);
}

.small {
  font-size: 0.85rem;
}

/* ---------- history page ---------- */

.empty-state {
  margin: 0 0 32px;
  padding: 24px;
  text-align: center;
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.history-section {
  margin-bottom: 32px;
}

.storage-note {
  margin: 0 0 24px;
  padding: 12px 14px;
  font-size: 0.9rem;
  background: var(--surface-2);
  border-radius: 12px;
}

.backup-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

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

.backup-status {
  margin: 12px 0 0;
  padding: 10px 14px;
  border-radius: 12px;
  border: 1.5px solid var(--relaxed);
  background: var(--surface);
}

.backup-status.error {
  border-color: var(--error);
  color: var(--error);
}

/* Under the session list (outside #historyContent, after its 32px margin): looks like the backup
   status, 12px under the list. Stays in the page while empty, so screen readers notice each new
   message, but then takes no space. */
.delete-status {
  margin: 0;
}

.delete-status:not(:empty) {
  margin: -20px 0 32px;
  padding: 10px 14px;
  border-radius: 12px;
  border: 1.5px solid var(--relaxed);
  background: var(--surface);
}

.delete-status.error:not(:empty) {
  border-color: var(--error);
  color: var(--error);
}

/* Only focused by the script (after the last session is deleted), never by tapping or Tab. */
#historyEmpty:focus {
  outline: none;
}

/* The session list's title with the Edit / Done button on the right. */
.list-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.list-head h2 {
  margin: 0;
}

.delete-summary {
  font-weight: 600;
}

.history-section > p {
  margin: 0 0 12px;
}

/* ---------- privacy page ---------- */

/* Lets the email address (or any long word) break at 320px instead of scrolling sideways. */
.privacy-page {
  overflow-wrap: anywhere;
}

.privacy-top {
  margin: 0 0 8px;
}

.privacy-section {
  margin-bottom: 28px;
}

.privacy-section p {
  margin: 0 0 12px;
}

.stat-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 10px;
}

.stat-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.stat-label {
  font-size: 0.85rem;
  color: var(--muted);
}

.stat-value {
  font-size: 1.7rem;
  font-weight: 800;
}

.chart {
  padding: 12px 8px 4px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 10px;
}

.chart:empty {
  display: none;
}

.chart svg {
  display: block;
  width: 100%;
  height: auto;
}

.chart-grid {
  stroke: var(--border);
  stroke-width: 1;
}

.chart-label {
  fill: var(--muted);
  font-size: 12px;
  font-family: inherit;
}

.chart-line {
  fill: none;
  stroke: var(--primary);
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.chart-point {
  fill: var(--surface);
  stroke: var(--primary);
  stroke-width: 2.5;
}

/* Time per week: earlier weeks lighter, the current week full color. */
.chart-bar {
  fill: var(--primary);
  opacity: 0.5;
}

.chart-bar.current {
  opacity: 1;
}

.day-parts,
.session-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.day-part {
  padding: 12px 14px;
  margin-bottom: 8px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
}

.day-part.best {
  border-color: var(--primary);
}

.day-part-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.day-part-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.day-part-track {
  height: 8px;
  margin: 8px 0 4px;
  background: var(--surface-2);
  border-radius: 999px;
  overflow: hidden;
}

.day-part-fill {
  height: 100%;
  background: var(--muted);
  border-radius: 999px;
}

.day-part.best .day-part-fill {
  background: var(--primary);
}

.session-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

.session-item:last-child {
  border-bottom: none;
}

/* Edit mode: the same two columns as above, plus the Delete button on a line of its own, so the
   session's text keeps its full width. */
.session-list.editing .session-item {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 12px;
  row-gap: 8px;
}

.session-delete {
  grid-column: 1 / -1;
  justify-self: end;
  color: var(--error);
}

.session-delete:hover {
  border-color: var(--error);
}

.session-list {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
}

/* "restarted": a session kept when Start over was chosen (endedBy "startOver"). */
.session-tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 1px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted);
  white-space: nowrap;
  vertical-align: 1px;
}

.session-item-focus {
  font-size: 1.2rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- character editor (avatar.html) ---------- */

.avatar-back {
  margin: 0 0 4px;
}

.avatar-page h1 {
  font-size: 1.6rem;
}

/* The preview stays at the top while the options scroll under it. Its height follows the screen,
   so a short (or landscape) phone keeps most of its height for the options. */
.avatar-preview {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 -16px 20px;
  padding: 8px 16px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

.avatar-preview-img {
  flex: 0 0 auto;
  width: clamp(72px, 32%, 150px);
  height: auto;
  max-height: 26vh;
  max-height: 26svh;
  aspect-ratio: 200 / 240;
  object-fit: contain;
}

/* The buttons take the rest of the row; with large text a long word may break rather than push
   the page wider than the screen. */
.avatar-preview-actions {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.avatar-preview-actions .btn {
  padding-left: 10px;
  padding-right: 10px;
  overflow-wrap: anywhere;
}

.editor-section {
  border: none;
  margin: 0 0 24px;
  padding: 0;
  min-width: 0;
}

.editor-section legend {
  padding: 0;
}

.editor-section .small {
  margin: 8px 0 0;
}

.editor-section legend h3 {
  margin: 0 0 10px;
  font-size: 1.05rem;
  line-height: 1.2;
}

/* The editor's groups (Costumes, Base, Clothes, Accessories): a tap on the title opens or closes
   one. The arrow turns when it's open. */
.editor-group {
  margin: 0 0 12px;
  border-top: 1px solid var(--border);
}

.editor-group > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 48px;
  padding: 8px 0;
  cursor: pointer;
  list-style: none;
}

.editor-group > summary::-webkit-details-marker {
  display: none;
}

.editor-group > summary h2 {
  margin: 0;
  font-size: 1.25rem;
  min-width: 0;
  overflow-wrap: anywhere;
}

.editor-group > summary::after {
  content: "";
  flex: 0 0 auto;
  width: 11px;
  height: 11px;
  margin: 0 6px 4px 0;
  border-right: 2.5px solid var(--text);
  border-bottom: 2.5px solid var(--text);
  transform: rotate(45deg);
  transition: transform 0.15s;
}

.editor-group[open] > summary::after {
  margin-bottom: -4px;
  transform: rotate(-135deg);
}

.editor-group > summary:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
  border-radius: 8px;
}

.editor-group-body {
  padding-top: 4px;
}

.editor-group-body > .small {
  margin: 0 0 10px;
}

/* Costume presets: buttons with a picture and a name. The columns get wider with larger text, so
   a name breaks between words, not inside one. */
.preset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(max(76px, 4em), 1fr));
  gap: 8px;
  margin: 0 0 24px;
}

.preset {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
  min-height: 44px;
  padding: 4px 4px 6px;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
}

@media (hover: hover) {
  .preset:hover {
    border-color: var(--primary);
  }
}

.preset:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
}

.preset-label {
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  overflow-wrap: anywhere;
  hyphens: auto;
}

/* A section of look options off screen isn't styled, laid out or painted at all (with every
   group open the page has ~2,000 elements; Randomize would otherwise redo them all). Its height
   until then comes from contain-intrinsic-size (avatar.js), then from its last real height. */
.editor-section-box {
  content-visibility: auto;
}

/* "No costume" on its own row, above the theme chips. */
.preset-grid-none {
  margin-bottom: 12px;
}

/* Costume themes: one radio group shown as chips. They wrap onto more lines when they don't fit
   (never a sideways-scrolling row). */
.theme-picker {
  margin: 0 0 12px;
  padding: 0;
  border: 0;
  min-width: 0;
}

.theme-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.theme-chip {
  position: relative;
  min-width: 0;
}

.theme-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.theme-chip-text {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 6px 16px;
  font-weight: 600;
  color: var(--text);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  overflow-wrap: anywhere;
}

.theme-input:checked + .theme-chip-text {
  color: var(--primary-text);
  background: var(--primary);
  border-color: var(--primary);
}

.theme-input:focus-visible + .theme-chip-text {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
}

/* The theme of the costume being worn. */
.theme-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary);
}

.theme-input:checked + .theme-chip-text .theme-dot {
  background: var(--primary-text);
}

.text-input {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
}

.text-input[aria-invalid="true"] {
  border-color: var(--error);
}

/* Radio-style grids: the real radio button is invisible (but focusable, so arrow keys and screen
   readers work as usual) and its picture or text is drawn next to it. */
.option-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(68px, 1fr));
  gap: 8px;
}

.option-grid-swatch {
  grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
}

.option-grid-text {
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}

.option-grid-full {
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
}

.option {
  position: relative;
  display: block;
  cursor: pointer;
  min-width: 0;
}

.option-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.option-visual {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  height: 100%;
  padding: 4px;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  font-weight: 600;
  text-align: center;
}

.option-input:checked + .option-visual {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--primary);
  background: color-mix(in srgb, var(--primary) 10%, var(--surface));
}

/* A check mark in the corner of the picked option, so it isn't marked by colour alone. */
.option-input:checked + .option-visual::after {
  content: "";
  position: absolute;
  top: -7px;
  right: -7px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--primary) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 10.5 L8.5 14 L15 6.5' fill='none' stroke='white' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 100% no-repeat;
}

.option-input:focus-visible + .option-visual {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
}

/* A thumbnail: inline SVG (avatar.js), with the proportions of its view (AVATAR_VIEWS). */
/* "Funny" before the funny faces, across the whole grid. */
.option-group-title {
  grid-column: 1 / -1;
  margin: 10px 0 0;
  font-size: 1rem;
}

.option-img {
  display: block;
  width: 100%;
  /* A redrawn thumbnail can't change anything else on the page, so the browser only lays out and
     paints that box again (much quicker when Randomize redraws every thumbnail on screen). */
  contain: layout paint style;
}

.option-img svg {
  display: block;
  width: 100%;
  height: 100%;
}

.option-img-head {
  aspect-ratio: 184 / 204;
}

.option-img-full {
  aspect-ratio: 200 / 240;
}

.option-swatch {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.2);
}

.personality-options {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* The personality badges keep their group colour, picked or not (they'd get the plain option
   background otherwise). The picked one gets a ring and the check mark. */
.personality-option .option-visual {
  padding: 8px 16px;
  font-size: 0.95rem;
  color: #fff;
  border: 2px solid transparent;
}

.personality-option .option-visual.badge-relaxed,
.personality-option .option-input:checked + .option-visual.badge-relaxed {
  background: var(--relaxed);
}

.personality-option .option-visual.badge-firm,
.personality-option .option-input:checked + .option-visual.badge-firm {
  background: var(--firm);
}

.personality-option .option-visual.badge-strict,
.personality-option .option-input:checked + .option-visual.badge-strict {
  background: var(--strict);
}

.personality-option .option-visual.badge-ragebait,
.personality-option .option-input:checked + .option-visual.badge-ragebait {
  background: var(--ragebait);
}

.personality-option .option-input:checked + .option-visual {
  border-color: var(--surface);
  box-shadow: 0 0 0 3px var(--text);
}

.personality-option .option-input:checked + .option-visual::after {
  background-color: var(--text);
}

.editor-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
}

.editor-actions .btn {
  flex: 1 1 140px;
}

#saveError {
  margin: 0 0 12px;
}

/* ---------- small screens ---------- */

@media (max-width: 380px) {
  .choice-group {
    grid-template-columns: 1fr;
  }

  /* Narrow dialogs: less padding, so "90 min" fits in a quarter of the continue/restart dialog
     at 320px, and both its steps fit a 320x568 screen without scrolling. */
  dialog {
    padding: 16px;
  }

  dialog .chips {
    gap: 6px;
  }

  dialog .chip {
    font-size: 0.9375rem;
    padding: 6px 2px;
  }

  #restartDialog h2 {
    margin-bottom: 8px;
  }

  #restartDialog p {
    margin-bottom: 12px;
  }

  /* Makes up for the 44px Custom field, so the dialog still fits 320x568. The note under the
     field keeps no bottom margin of its own ("#restartDialog p" above), so these 10px are the gap. */
  #restartDuration {
    margin-bottom: 10px;
  }

  #restartDialog .custom-note {
    margin-bottom: 0;
  }
}

/* Short screens: the session image takes only the height that's left, so every
   distraction button fits above the sticky bottom bar without scrolling. 460px is the
   rest of the session screen (header, timer, two rows of buttons, bar) plus a little room.
   svh = the height while the browser's address bar is showing (vh is the fallback).
   The summary image and taller phones keep the normal size. */
@media (max-height: 740px) {
  #sessionImg {
    height: clamp(120px, calc(100vh - 460px), 260px);
    height: clamp(120px, calc(100svh - 460px), 260px);
    object-fit: contain;
  }
}

/* ---------- wide and landscape screens (index.html: setup and session) ---------- */

/* The session screen's two wrappers (index.html). In portrait they make no box of their own, so
   their children lay out (and the bottom bar sticks) exactly as if the wrappers weren't there. */
.session-side,
.session-main {
  display: contents;
}

/* Two columns: laptops, desktops and landscape tablets (900px wide or more, landscape), and
   landscape phones (any width, under 500px tall). A portrait tablet, even a large one, keeps the
   single column. Only index.html (.app-timer); the other pages keep their 600px column.
   See "Layout (screen sizes)" in the README. */
@media (min-width: 900px) and (orientation: landscape), (orientation: landscape) and (max-height: 500px) {
  .app-timer {
    max-width: 1200px;
  }

  /* Setup: only step 1 (the character grid) uses the full width. Everything else keeps today's
     600px column, centred, so lines of text don't get long. Same for the summary and the
     "open in another tab" notice. */
  #setupScreen > :not(#characterStep),
  #summaryScreen,
  #elsewhereScreen {
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
  }

  /* As many cards per row as fit (7 on a laptop, 5 on a landscape phone), each at least 150px
     wide: about the width of a card on a 320px phone today. */
  .character-list {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  }

  /* Session: the character on the left, the timer and buttons on the right, vertically centred.
     position: relative: landscape phones place the category picker and the motivation card over
     the character column (below). */
  #sessionScreen {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 40px;
    align-items: center;
  }

  /* The full height of the screen minus the page's top and bottom padding (24px + 40px), so the
     page doesn't scroll. svh = the height while the browser's address bar is showing (vh is the
     fallback for older browsers). */
  .session-side {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 64px);
    height: calc(100svh - 64px);
    min-height: 280px;
  }

  /* The character gets whatever height is left under the info line and notes. */
  .session-side .stage {
    position: relative;
    flex: 1 1 0;
    min-height: 80px;
  }

  /* Fills the stage, scaled to fit inside it whatever the art's aspect ratio: never cropped or
     stretched (object-fit: contain). Anchored at the bottom, where the animations pivot.
     Absolute, so the image's own size never makes the stage taller. */
  #sessionImg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: 50% 100%;
  }

  .session-main {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 520px;
    justify-self: center;
  }

  .timer {
    font-size: clamp(4rem, 6vw, 5.5rem);
  }

  /* Only as wide as its column now, not the whole screen. */
  .session-bar {
    margin: 24px 0 0;
    padding: 12px 0 calc(12px + env(safe-area-inset-bottom));
  }
}

/* Landscape phones: height is the tight dimension. Everything is tighter, so the timer, both rows
   of distraction buttons and the bottom bar fit without scrolling in about 250px (a 740x360 phone
   in Chrome with the address bar showing has about 265px). The category picker and the motivation
   card take the distraction buttons' place instead of pushing anything down (see below). */
@media (orientation: landscape) and (max-height: 500px) {
  .app-timer {
    padding-top: 8px;
    padding-bottom: 8px;
  }

  #sessionScreen {
    grid-template-columns: 40% minmax(0, 1fr);
    column-gap: 20px;
  }

  .session-side {
    height: calc(100vh - 16px);
    height: calc(100svh - 16px);
    min-height: 0;
  }

  .session-info {
    margin-bottom: 4px;
  }

  .screen-note {
    margin: 0 0 4px;
  }

  .timer-block {
    margin: 0 0 6px;
  }

  .timer {
    font-size: 2.5rem;
    line-height: 1.1;
  }

  .distraction h2 {
    font-size: 1rem;
    margin-bottom: 6px;
  }

  .distraction-buttons {
    gap: 6px;
  }

  /* Advanced: four per row even in a narrow column (568x320), so the seven lengths stay on two rows. */
  .distraction-buttons.advanced {
    grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
  }

  /* Still at least 44px tall. */
  .btn.level {
    padding-top: 9px;
    padding-bottom: 9px;
  }

  /* The right column is a grid of three rows: the timer, the "block" (the distraction buttons with
     their question) and the bar's buttons. The category picker and the motivation card are placed
     exactly over the block, so they take the distraction buttons' place: the block keeps its
     height and the timer and the bar never move. Everything fits the screen, so the bar doesn't
     need to stick: it has no box of its own here (display: contents), and its picker, Motivate me
     / Undo and End session become cells of this grid. */
  .session-main {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "timer timer"
      "block block"
      "left right";
    column-gap: 8px;
  }

  .timer-block {
    grid-area: timer;
  }

  .distraction {
    grid-area: block;
  }

  .session-bar {
    display: contents;
  }

  .session-bar > .btn {
    margin-top: 8px;
    padding-top: 10px;
    padding-bottom: 10px;
  }

  /* Motivate me and Undo share one cell: only one of them is ever shown. */
  #motivateButton,
  #undoButton {
    grid-area: left;
  }

  #endButton {
    grid-area: right;
  }

  /* Over the block, exactly its size (absolute, so they never make it taller). The picker wins
     over the card: app.js closes the card when the picker opens, and a card opened while the
     picker is showing waits under it. */
  .category-picker,
  .motivation-card {
    grid-area: block;
    position: absolute;
    inset: 0;
    margin: 0;
  }

  .motivation-card {
    z-index: 1;
  }

  .category-picker {
    z-index: 2;
  }

  /* The distraction buttons under them keep their space but can't be seen, tapped, focused or read
     out; they're back as soon as the picker closes (a category, Skip or its auto-close) and the
     card is closed with its ×. */
  .session-main:has(> .motivation-card:not([hidden])) .distraction,
  .session-main:has(.category-picker:not([hidden])) .distraction {
    visibility: hidden;
  }

  /* The picker in the block's ~120px, laid out like the block it replaces: the question on top,
     the six categories in two rows of three, and Skip on the right, as tall as both rows (still a
     plain grey button). Its head and button row have no box of their own here. No card frame:
     there's no room for one, and it stands where the distraction buttons were. */
  .category-picker {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
    gap: 6px;
    align-content: start;
    padding: 0;
    background: var(--bg);
    border: none;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
  }

  .category-head,
  .category-buttons {
    display: contents;
  }

  /* Same size and spacing as the question it replaces ("Got distracted? How much?"). */
  .category-prompt {
    grid-column: 1 / -1;
    font-size: 1rem;
    line-height: 1.2;
    text-align: center;
  }

  .category-picker .skip-btn {
    grid-column: 4;
    grid-row: 2 / span 2;
    min-width: 60px;
  }

  /* A touch smaller, so "Thoughts" fits a third of the picker even on a 568x320 phone. */
  .category-buttons .btn {
    padding: 8px 2px;
    font-size: 0.9375rem;
  }

  /* The card fills the block. If its message doesn't fit, app.js (fitMotivationCard) makes the
     text a step smaller (fit-1, then fit-2); if even that doesn't fit, it scrolls inside the card.
     It never grows the block, so it can't push the bar off the screen. */
  .motivation-card {
    padding: 8px 44px 8px 12px;
    font-size: 0.9375rem;
    overflow-y: auto;
  }

  .motivation-card.fit-1 {
    font-size: 0.875rem;
  }

  .motivation-card.fit-2 {
    font-size: 0.8125rem;
  }

  .motivation-card p {
    margin-top: 2px;
  }

  /* index.html's dialogs (they follow its <main>; history.html's keep their look): less padding,
     and anything taller than the screen scrolls inside the dialog. */
  .app-timer ~ dialog {
    padding: 16px;
    max-height: calc(100vh - 16px);
    max-height: calc(100svh - 16px);
    overflow-y: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .char-img,
  .stage {
    animation: none !important;
  }

  .editor-group > summary::after {
    transition: none;
  }
}
