/* assets/css/tarot-reading.css
   ============================================================
   Tarot Reading page.

   Follows the site's design language like every other page: canonical
   glass panels and popups (12px radius), translucent rounded buttons in
   the system UI font with the teal accent-button for the main action,
   small bold uppercase labels, and the AGENTS.md active-state recipe.
   The only thing that is the tarot page's own is the field behind it.

   The field is a smoke-and-stars sky. tarot-sky.js paints it once onto
   one square (clouds and stars together, plus a twinkle layer on the same
   square); CSS turns that square as one piece, so the sky moves with no
   render loop. The 3D stage is transparent and has no stars of its own,
   so this one sky sits behind the log list, the reading popup and the
   cards. This page opts out of nav-global's idle pause (AGENTS.md).
   Everything here is scoped under .tarot-page so the void palette cannot
   leak into the sidebar or any shared component.
   ============================================================ */

.tarot-page {
  /* --- Palette: the site's text, border and accent values -------- */
  --tr-bg: #000000;
  --tr-text: #eaf2f8;
  --tr-text-2: rgba(234, 242, 248, 0.72);
  --tr-text-3: rgba(234, 242, 248, 0.5);
  --tr-text-4: rgba(234, 242, 248, 0.28);
  --tr-hairline: rgba(255, 255, 255, 0.1);
  --tr-border: rgba(255, 255, 255, 0.15);
  --tr-border-active: rgba(255, 255, 255, 0.32);
  --tr-gold: var(--accent);
  --tr-gold-rgb: var(--accent-rgb);
  --tr-warning: #ff9f0a;


  /* --- Easings ----------------------------------------------------- */
  --ease-cinematic: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-quiet: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);

  /* --- Radii: the site's 10px controls and 12px surfaces ---------- */
  --tr-r0: 0;
  --tr-r1: 10px;
  --tr-r2: 12px;
  --tr-pill: 999px;

  /* Control height, stepped down the breakpoints (never below 44 on
     phones — that is our tap-target floor). */
  --tr-btn-h: 44px;

  /* Written by tarot-page.js while the scene builds. */
  --scene-load-progress: 0%;
}

/* cross-platform-compat.css sets `body { background-color:#0b1020 !important }`
   for the whole site. The tarot page is the one page that is a black field,
   so it has to answer with the same weight. */
body.tarot-page {
  background-color: #000000 !important;
}

/* The sky fills the whole viewport, below every layer, so the glass
   sidebar frosts it like the artwork behind other pages. tarot-sky.js adds
   the canvases and .is-painted; without WebGL the smoke is skipped and the
   stars still paint. */
.tr-void {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background-color: var(--tr-bg);
  opacity: 0;
  transition: opacity 0.6s var(--ease-quiet);
}

.tr-void.is-painted {
  opacity: 1;
}

/* One sky: the clouds and every star are painted on the same square and
   move as one piece. .tr-void-drift carries the extra swing during the
   shuffle; .tr-void-sky carries the slow turn. Oversized and centred so
   the corners never show at any angle. */
.tr-void-drift {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  -webkit-transform: rotate(0deg) scale(1);
  transform: rotate(0deg) scale(1);
  -webkit-transition: -webkit-transform 2.4s var(--ease-quiet);
  transition: transform 2.4s var(--ease-quiet);
}

.tarot-page.tr-sky-swirl .tr-void-drift {
  -webkit-transform: rotate(-38deg) scale(1.12);
  transform: rotate(-38deg) scale(1.12);
  -webkit-transition: -webkit-transform 11s cubic-bezier(0.45, 0, 0.25, 1);
  transition: transform 11s cubic-bezier(0.45, 0, 0.25, 1);
}

.tr-void-sky {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 150vmax;
  height: 150vmax;
  margin: -75vmax 0 0 -75vmax;
  -webkit-animation: trSkyTurn 360s linear infinite;
  animation: trSkyTurn 360s linear infinite;
  will-change: transform;
}

.tr-void-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
}

/* The brighter stars and glints, on the same square, breathing in place. */
.tr-void-twinkle {
  -webkit-animation: trTwinkle 4.4s ease-in-out infinite alternate;
  animation: trTwinkle 4.4s ease-in-out infinite alternate;
}

html.tr-sky-rest .tr-void-sky,
html.tr-sky-rest .tr-void-twinkle {
  -webkit-animation-play-state: paused;
  animation-play-state: paused;
}

@-webkit-keyframes trSkyTurn {
  0%   { -webkit-transform: rotate(0deg) scale(1); transform: rotate(0deg) scale(1); }
  50%  { -webkit-transform: rotate(180deg) scale(1.08); transform: rotate(180deg) scale(1.08); }
  100% { -webkit-transform: rotate(360deg) scale(1); transform: rotate(360deg) scale(1); }
}

@keyframes trSkyTurn {
  0%   { -webkit-transform: rotate(0deg) scale(1); transform: rotate(0deg) scale(1); }
  50%  { -webkit-transform: rotate(180deg) scale(1.08); transform: rotate(180deg) scale(1.08); }
  100% { -webkit-transform: rotate(360deg) scale(1); transform: rotate(360deg) scale(1); }
}

@-webkit-keyframes trTwinkle { from { opacity: 1; } to { opacity: 0.3; } }
@keyframes trTwinkle { from { opacity: 1; } to { opacity: 0.3; } }

/* ============================================================
   1. Page shell
   ============================================================ */

/* A narrow centred column on the wide sky field, not a
   full-width dashboard. 880px puts the reading-type grid at two columns, so
   each variant gets room to read as a card instead of a label. */
.tarot-container {
  width: 100%;
  margin: 0 auto;
  padding: 20px 20px 104px;
  box-sizing: border-box;
  min-width: 0;
}

/* Same heading as Campaigns / Expansions: left-aligned 28px Birmingham
   title over one line of 16px copy. */
.tarot-header {
  position: relative;
  z-index: 4999;
  min-width: 0;
  margin: 0 0 24px;
}

.tarot-page h1.tarot-title {
  font-family: 'Birmingham', 'Times New Roman', serif;
  font-weight: 700;
  color: #fff;
  font-size: 28px;
  line-height: 1.2;
  margin: 24px 0 8px;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  overflow-wrap: anywhere;
}

/* "Keep screen awake", top left above the title. */
.tr-awake {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 0 14px 0 12px;
  max-width: 100%;
  box-sizing: border-box;
  border-radius: var(--tr-pill);
  background: rgba(17, 26, 34, 0.35);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: var(--tr-text);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-awake {
    background: rgba(17, 26, 34, 0.62);
  }
}

.tr-awake span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.tr-awake input {
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.tr-awake:hover {
  border-color: rgba(255, 255, 255, 0.3);
}

.tr-awake:focus-within {
  border-color: var(--accent-border);
}

.tr-awake.is-on {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: #fff;
  box-shadow: 0 0 0 2px var(--accent), 0 0 14px var(--accent-glow);
}

.tarot-page .tr-awake + h1.tarot-title {
  margin-top: 16px;
}

/* Out of sight, but still "playing" so the OS keeps the screen on. */
.tr-awake-video {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  z-index: -1;
}

.tarot-subtitle {
  color: rgba(255, 255, 255, 0.95);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  margin: 0;
  overflow-wrap: anywhere;
}

/* Once a reading starts the stage owns the viewport: the whole landing
   column (title included) steps aside until Start over. */
.tarot-page.is-reading .tarot-container {
  display: none;
}

/* Field captions and eyebrows: the site's small bold uppercase label. */
.tr-label,
.tr-eyebrow {
  display: block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-2);
  margin: 0 0 10px;
  min-width: 0;
  overflow-wrap: anywhere;
}

.tr-eyebrow {
  margin-bottom: 6px;
}

.tarot-page h2.tr-section-title {
  font-family: 'Birmingham', 'Times New Roman', serif;
  font-weight: 700;
  color: #fff;
  font-size: clamp(20px, 3vw, 26px);
  margin: 0;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

/* ============================================================
   2. Panels (canonical glass recipe)
   ============================================================ */

/* The canonical glass recipe, verbatim. The only additions are an inner
   top highlight and a deeper drop shadow: over a near-black field the
   recipe alone has nothing to refract and reads as a flat grey slab,
   which is most of why the operator called the page "designless". The
   highlight gives the panel an edge and the shadow gives it altitude —
   neither changes the fill, the blur or the border. */
.tr-panel {
  position: relative;
  z-index: 1001; /* content sits above the fixed stage */
  background: rgba(17, 26, 34, 0.18);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 12px;
  box-shadow:
    0 4px 20px rgba(0, 0, 0, 0.25),
    0 24px 64px rgba(0, 0, 0, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.07);
  color: #fff;
  padding: clamp(20px, 3vw, 30px);
  margin: 0 0 20px;
  min-width: 0;
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-panel {
    background: rgba(17, 26, 34, 0.62);
  }
}

/* ---------- guide: how readings, rows and rerolls work ---------- */
.tr-guide-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(420px, 100%), 1fr));
  gap: 12px;
  min-width: 0;
}

.tr-guide-item {
  min-width: 0;
  padding: 16px 18px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
}

.tarot-page .tr-guide-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  color: #fff;
}

.tr-guide-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-warning);
  border: 1px solid currentColor;
  border-radius: 999px;
}

.tr-guide-item p {
  margin: 0 0 8px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--tr-text-2);
  overflow-wrap: anywhere;
}

.tr-guide-item p:last-child {
  margin-bottom: 0;
}

.tr-guide-item strong,
.tr-guide-item em {
  color: #fff;
}

.tr-guide-item .tr-guide-note {
  font-size: 12px;
  color: var(--tr-text-3);
}

/* Title above actions on phones — the agreed header pattern. */
.tr-panel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 0 0 22px;
  padding: 0 0 18px;
  border-bottom: 1px solid var(--tr-hairline);
}

.tr-panel-head .tr-panel-head-title {
  flex: 1 1 auto;
  min-width: 0;
}

.tr-panel-head-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* The guide opens on demand; collapsed it is just its heading. */
.tr-guide.is-collapsed .tr-panel-head {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}

.tr-guide .tr-panel-head {
  cursor: pointer;
}

.tr-guide-grid[hidden] {
  display: none;
}

.tr-guide-chevron {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-top: -3px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
  -webkit-transition: -webkit-transform 0.2s ease, margin 0.2s ease;
  transition: transform 0.2s ease, margin 0.2s ease;
}

.tr-guide-toggle[aria-expanded="true"] .tr-guide-chevron {
  margin-top: 3px;
  -webkit-transform: rotate(-135deg);
  transform: rotate(-135deg);
}

@media (prefers-reduced-motion: reduce) {
  .tr-guide-chevron {
    -webkit-transition: none;
    transition: none;
  }
}

/* ============================================================
   3. Buttons — one recipe for every text button on the page
   ============================================================
   Same geometry as the site's buttons; no hover bounce, so there is no
   translateY on :hover or :active here. */

.tr-btn {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  box-sizing: border-box;
  height: var(--tr-btn-h);
  min-height: var(--tr-btn-h);
  padding: 0 22px;
  max-width: 100%;
  min-width: 0;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  background: rgba(var(--accent-button-rgb), 0.72);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  color: #fff;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-align: center;
  text-decoration: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 4px 16px rgba(0, 0, 0, 0.28);
  cursor: pointer;
  transition: background 0.25s var(--ease-quiet), border-color 0.25s var(--ease-quiet),
    box-shadow 0.25s var(--ease-quiet), opacity 0.25s var(--ease-quiet);
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-btn {
    background: rgba(var(--accent-button-rgb), 0.95);
  }
}

.tr-btn:hover:not(:disabled):not([aria-disabled="true"]) {
  background: var(--accent-button-hover);
  border-color: var(--accent-border);
}

.tr-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.tr-btn:disabled,
.tr-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

.tr-btn-primary {
  background: rgba(var(--accent-button-rgb), 0.72);
}

/* Secondary: the site's translucent glass button. */
.tr-btn-quiet {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.18);
  font-weight: 600;
  box-shadow: none;
}

.tr-btn-quiet:hover:not(:disabled):not([aria-disabled="true"]) {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.3);
}

/* --- Loading state: a determinate bar plus a shimmer ----------------
   The fill is a hard gradient stop at --scene-load-progress, which
   tarot-page.js advances from the scene's own onProgress callback. */
.tr-btn.is-loading {
  position: relative;
  overflow: hidden;
  cursor: wait;
  background-image: linear-gradient(
    to right,
    rgba(var(--accent-rgb), 0.42) 0,
    rgba(var(--accent-rgb), 0.42) var(--scene-load-progress, 0%),
    rgba(255, 255, 255, 0.06) var(--scene-load-progress, 0%),
    rgba(255, 255, 255, 0.06) 100%
  );
  opacity: 1;
}

.tr-btn.is-loading::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.22) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  transform: translateX(-100%);
  animation: trShimmer 1.25s linear infinite;
  pointer-events: none;
}

@keyframes trShimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* Icon-only control (the trash button in Past readings). It carries the
   fixed-white .icon-trash glyph, so it keeps a transparent surface
   rather than the accent fill. */
.tr-icon-btn {
  -webkit-appearance: none;
  appearance: none;
  width: 44px;
  height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--tr-r1);
  color: var(--tr-text);
  cursor: pointer;
  transition: background 0.3s var(--ease-quiet), border-color 0.3s var(--ease-quiet);
}

.tr-icon-btn:hover,
.tr-icon-btn:focus-visible {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--tr-border-active);
  outline: none;
}

/* ============================================================
   4. Campaign logs and the reading popup (.modal + .modal-panel)
   ============================================================
   `.modal` brings the canonical dim layer and the sidebar-aware
   centering from glass-modals.css; `.modal-panel` brings the canonical
   glass surface. Everything below is layout on top. */

.tarot-page .tr-picker {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  box-sizing: border-box;
  opacity: 0;
  transition: opacity 0.3s var(--ease-cinematic);
}

.tarot-page .tr-picker[hidden] {
  display: none;
}

.tarot-page .tr-picker.is-open {
  opacity: 1;
}

.tarot-page .tr-picker-panel {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 560px;
  max-height: min(86vh, 780px);
  min-width: 0;
  padding: 0;
  box-sizing: border-box;
  overflow: hidden;
}

.tarot-page .tr-picker-head {
  flex: 0 0 auto;
  padding: 28px 32px 20px;
  border-bottom: 1px solid var(--tr-hairline);
  min-width: 0;
}

/* Popup heading: white / 700 / UI font per AGENTS.md. (The brief called the
   UI font a defect and wanted Birmingham here; AGENTS.md's "every heading
   inside a popup keeps the regular UI font" rule wins, so the display
   character comes from the eyebrow and the gold rule instead.) */
.tarot-page .tr-picker-panel h2.tr-picker-title {
  margin: 0;
  padding: 0;
  font-family: inherit;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: normal;
  color: #fff;
  text-align: left;
  border: 0;
  overflow-wrap: anywhere;
}

.tarot-page .tr-picker-lede {
  margin: 10px 0 0;
  font-size: 13px;
  font-weight: 300;
  line-height: 1.6;
  color: var(--tr-text-2);
  overflow-wrap: anywhere;
}

.tarot-page .tr-picker-list {
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  padding: 22px 32px 26px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  touch-action: pan-y;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  /* custom-scrollbars.css paints an 8px slate-grey thumb site-wide, which
     is the "raw scrollbar" showing through the glass here. Narrow it and
     tint it white so it reads as part of the glass. */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}

.tarot-page .tr-picker-list::-webkit-scrollbar {
  width: 4px;
}

.tarot-page .tr-picker-list::-webkit-scrollbar-track {
  background: transparent;
}

.tarot-page .tr-picker-list::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.22);
  border-radius: 2px;
}

.tarot-page .tr-picker-list::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.4);
}

/* The list fades out at both ends instead of being cut by a hard edge, so
   a scrolled list reads as continuing rather than clipped. Masking is
   gated: browsers without it simply keep the hard edge. */
@supports ((mask-image: linear-gradient(#000, #000)) or (-webkit-mask-image: linear-gradient(#000, #000))) {
  .tarot-page .tr-picker-list {
    -webkit-mask-image: linear-gradient(to bottom,
      rgba(0, 0, 0, 0) 0, #000 18px, #000 calc(100% - 22px), rgba(0, 0, 0, 0) 100%);
    mask-image: linear-gradient(to bottom,
      rgba(0, 0, 0, 0) 0, #000 18px, #000 calc(100% - 22px), rgba(0, 0, 0, 0) 100%);
  }
}

.tarot-page .tr-picker-note {
  flex: 0 0 auto;
  margin: 0;
  padding: 16px 32px 22px;
  border-top: 1px solid var(--tr-hairline);
  font-weight: 700;
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-3);
  overflow-wrap: anywhere;
}

.tarot-page .tr-picker-note a {
  color: var(--tr-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- The campaign-log list (landing page) --------------------------- */

.tr-loglist {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(440px, 100%), 1fr));
  gap: 10px;
  min-width: 0;
}

/* Campaign logs stay on a single row. tarot-page.js sets the column
   count to however many 440px tracks fit, and pages the rest. Until
   that runs, one column cannot wrap into a second row. */
#trLogList.tr-loglist {
  grid-template-columns: minmax(0, 1fr);
}

.tr-logpager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 10px;
  margin-top: 12px;
  min-width: 0;
}

.tr-logpager[hidden] {
  display: none;
}

.tr-logpager-label {
  min-width: 0;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
  color: #fff;
  text-align: center;
}

.tr-loglist > * {
  min-width: 0;
}

.tr-loglist-note {
  margin: 16px 0 0;
}

.tr-loglist-note:empty {
  display: none;
}

.tr-loglist-note a {
  color: var(--tr-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Beats the later .tr-hint margin, which otherwise drops the space
   under this line and sticks it to the rows. */
.tr-hint.tr-standalone-lead {
  margin: 0 0 16px;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.78);
}

.tr-logrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
  padding: 12px;
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  min-width: 0;
  transition: border-color 0.3s var(--ease-quiet), background-color 0.3s var(--ease-quiet);
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-logrow {
    background: rgba(17, 26, 34, 0.62);
  }
}

.tr-logrow:hover {
  border-color: rgba(255, 255, 255, 0.22);
  background-color: rgba(255, 255, 255, 0.1);
}

.tr-logrow-art,
.tr-read-art {
  flex: 0 0 auto;
  display: block;
  width: 120px;
  height: 80px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

.tr-logrow-art img,
.tr-read-art img {
  display: block;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
  object-fit: cover;
}

/* Observed's art is a player card, so the frame matches the card instead
   of the wide campaign-box crop. */
.tr-logrow-art.is-card {
  width: 78px;
  height: 111px;
}

.tr-read-art.is-card {
  width: 68px;
  height: 97px;
}

/* Standalone: a small fanned stack of whole tarot backs, in the same
   card-shaped slot Observed uses. Each card keeps the back's 1:1.73. */
.tr-logrow-art.is-stack,
.tr-read-art.is-stack {
  position: relative;
  width: 78px;
  height: 111px;
  background: none;
  border: 0;
  border-radius: 0;
  overflow: visible;
}

.tr-read-art.is-stack {
  width: 68px;
  height: 97px;
}

.tr-logrow-art .tr-stack-card,
.tr-read-art .tr-stack-card {
  position: absolute;
  width: 66%;
  height: 81%;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.55);
  -o-object-fit: cover;
  object-fit: cover;
  -webkit-transform-origin: 50% 90%;
  transform-origin: 50% 90%;
}

.tr-stack-card:nth-child(1) {
  left: 6%;
  top: 13%;
  -webkit-transform: rotate(-9deg);
  transform: rotate(-9deg);
}

.tr-stack-card:nth-child(2) {
  left: 18%;
  top: 8%;
  -webkit-transform: rotate(-2deg);
  transform: rotate(-2deg);
}

.tr-stack-card:nth-child(3) {
  left: 30%;
  top: 4%;
  -webkit-transform: rotate(8deg);
  transform: rotate(8deg);
}

.tr-logrow-body {
  flex: 1 1 220px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.tr-logrow-name {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
  color: #fff;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.tr-logrow-meta,
.tr-read-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--tr-text-2);
  min-width: 0;
}

.tr-logrow-sub {
  color: var(--tr-text-3);
}

.tr-logrow-meta > span,
.tr-read-meta > span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.tr-logrow-meta > span + span::before,
.tr-read-meta > span + span::before {
  content: '·';
  margin-right: 8px;
  color: var(--tr-text-4);
}

.tr-logrow-reason {
  font-weight: 700;
  font-size: 11px;
  line-height: 1.6;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-warning);
  overflow-wrap: anywhere;
}

.tr-logrow-action {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  min-width: 0;
}

.tr-logrow-action .tr-btn {
  padding: 0 22px;
}

.tr-logrow.is-blocked .tr-logrow-art,
.tr-logrow.is-blocked .tr-logrow-name {
  opacity: 0.55;
}

/* --- The reading popup ---------------------------------------------- */

/* As big as the window allows, so the reading types and the reading log
   usually fit without scrolling; the body still scrolls on short screens. */
.tarot-page .tr-read-panel {
  max-width: 1520px;
  max-height: calc(100vh - 40px);
}

@supports (height: 100dvh) {
  .tarot-page .tr-read-panel {
    max-height: calc(100dvh - 40px);
  }
}

.tr-read-head {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
  padding: 22px 28px 18px;
  border-bottom: 1px solid var(--tr-hairline);
  min-width: 0;
}

.tr-read-art {
  width: 96px;
  height: 64px;
}

.tr-read-heading {
  flex: 1 1 220px;
  min-width: 0;
}

.tr-read-heading .tr-eyebrow {
  margin-bottom: 4px;
}

.tr-read-meta {
  margin-top: 6px;
}

.tr-read-head-actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  min-width: 0;
}

.tr-read-head-actions .tr-btn {
  padding: 0 18px;
}

.tr-read-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 22px 28px 26px;
  box-sizing: border-box;
  overflow-y: auto;
  touch-action: pan-y;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}

.tr-read-body::-webkit-scrollbar {
  width: 4px;
}

.tr-read-body::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.22);
  border-radius: 2px;
}

.tr-read-foot {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 10px 18px;
  padding: 16px 28px;
  border-top: 1px solid var(--tr-hairline);
  min-width: 0;
}

/* The site's bug-report button sits in the corner the Begin button
   reaches, so it steps aside while the reading popup is open. */
body.tarot-page.modal-open .ah-bug-fab {
  visibility: hidden;
  pointer-events: none;
}

.tr-read-history {
  margin: 26px 0 0;
  padding: 22px 0 0;
  border-top: 1px solid var(--tr-hairline);
}

.tr-read-history .tr-empty {
  padding: 22px 16px;
}

.tr-hint.tr-history-note {
  margin: 12px 0 0;
}

.tr-hint.tr-history-note[hidden] {
  display: none;
}

.tr-retention .tr-hint {
  margin: 14px 0 0;
}

.tr-view-delete {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.tr-label-short {
  display: none;
}

/* Topbar while a past reading is on the stage: no Save, and Delete only
   once the cards are up (and only for the reader's own reading). */
.tarot-page.is-viewing #trSave,
.tarot-page:not(.is-viewing) #trViewDelete,
.tarot-page:not(.is-revealed) #trViewDelete,
#trViewDelete[hidden] {
  display: none;
}

.tr-history-item.is-openable {
  cursor: pointer;
  transition: border-color 0.3s var(--ease-quiet);
}

.tr-history-item.is-openable:hover {
  border-color: var(--tr-border-active);
}

.tr-history-open {
  height: 32px;
  min-height: 32px;
  padding: 0 12px;
  border-radius: 9px;
  font-size: 12.5px;
}

/* Reroll and Delete live in a menu behind the gear in the row's corner. */
.tr-history-item {
  position: relative;
}

.tr-history-item.is-menu-open {
  z-index: 5;
}

.tr-history-item.has-gear .tr-history-main {
  padding-right: 36px;
}

.tr-history-gear {
  position: absolute;
  top: 8px;
  right: 8px;
}

.tr-history-gear-btn {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  cursor: pointer;
  opacity: 0.7;
  transition: background 0.2s var(--ease-quiet), border-color 0.2s var(--ease-quiet), opacity 0.2s var(--ease-quiet);
}

.tr-history-gear-btn:hover,
.tr-history-gear-btn:focus-visible,
.tr-history-gear.is-open .tr-history-gear-btn {
  opacity: 1;
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.18);
  outline: none;
}

.tr-gear-icon {
  display: block;
  width: 18px;
  height: 18px;
  background: url('/assets/icons/gear.svg?v=2026-10-18-gear') center / contain no-repeat;
}

.tr-history-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 170px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-sizing: border-box;
  background: rgba(17, 26, 34, 0.18);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
}

@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .tr-history-menu {
    background: rgba(17, 26, 34, 0.62);
  }
}

.tr-history-menu[hidden] {
  display: none;
}

.tr-history-menu-item {
  -webkit-appearance: none;
  appearance: none;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.tr-history-menu-item:hover,
.tr-history-menu-item:focus-visible {
  background: rgba(255, 255, 255, 0.1);
  outline: none;
}

.tr-history-menu-item.tr-history-delete {
  color: #ff8a80;
}

/* Touch screens keep the 44px tap target. */
@media (pointer: coarse) {
  .tr-history-open,
  .tr-history-menu-item {
    min-height: 44px;
  }

  .tr-history-open {
    height: 44px;
  }

  .tr-history-gear {
    top: 4px;
    right: 4px;
  }

  .tr-history-gear-btn {
    width: 44px;
    height: 44px;
  }

  .tr-history-item.has-gear .tr-history-main {
    padding-right: 44px;
  }
}

.tr-count {
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-3);
}

/* Card skins. A palette button at the bottom of the page opens the
   panel above it. Hidden during a reading so it never sits on the table. */
.tr-skins {
  position: fixed;
  z-index: 1004;
  left: calc(var(--layout-sidebar-width, 240px) + 16px);
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: 10px;
  max-width: calc(100vw - var(--layout-sidebar-width, 240px) - 88px);
  min-width: 0;
}

.tr-switch {
  position: static;
  flex: none;
  width: 48px;
  height: 48px;
}

.tarot-page.is-reading .tr-skins {
  display: none;
}

.tr-skins-btn {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  box-sizing: border-box;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: rgba(17, 26, 34, 0.18);
  color: #fff;
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}

.tr-skins-btn[aria-expanded="true"],
.tr-skins-btn:hover,
.tr-skins-btn:focus-visible {
  border-color: var(--accent-border);
  background: var(--accent-soft);
  box-shadow: 0 0 0 2px var(--accent), 0 0 14px var(--accent-glow);
  outline: none;
}

.tr-skins-panel {
  position: absolute;
  left: 0;
  bottom: 58px;
  width: min(360px, calc(100vw - var(--layout-sidebar-width, 240px) - 96px));
  min-width: 0;
  box-sizing: border-box;
  color: #fff;
  background: rgba(17, 26, 34, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  overflow: hidden;
}

.tr-skins-panel[hidden] {
  display: none;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .tr-skins-btn,
  .tr-skins-panel {
    background: rgba(17, 26, 34, 0.62);
  }
}

.tr-skins-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
}

.tr-skins-glyph {
  flex: none;
}

.tr-skins-list {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.tr-skins-opt {
  -webkit-appearance: none;
  appearance: none;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-width: 0;
  min-height: 48px;
  margin: 0;
  padding: 10px 14px 10px 16px;
  box-sizing: border-box;
  border: 0;
  border-left: 3px solid transparent;
  background: transparent;
  color: rgba(255, 255, 255, 0.88);
  font: inherit;
  font-size: 15px;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}

.tr-skins-opt + .tr-skins-opt {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.tr-skins-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: break-word;
}

.tr-recommended {
  flex: none;
  align-self: center;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid rgba(48, 209, 88, 0.55);
  background: rgba(48, 209, 88, 0.16);
  color: #30d158;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tr-skins-check,
.tr-skins-lock {
  flex: none;
}

.tr-skins-check {
  display: none;
  color: var(--accent);
}

.tr-skins-opt.is-on {
  background: var(--accent-soft);
  border-left-color: var(--accent);
  color: #fff;
  box-shadow: inset 0 0 0 1px var(--accent-border), 0 0 14px var(--accent-glow);
}

.tr-skins-opt.is-on .tr-skins-check {
  display: block;
}

.tr-skins-opt.is-locked {
  color: rgba(255, 255, 255, 0.45);
  cursor: not-allowed;
}

.tr-skins-lock {
  display: none;
}

.tr-skins-opt.is-locked .tr-skins-lock {
  display: block;
  color: #e6c27a;
}

.tr-skins-opt:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.tr-modes {
  display: grid;
  /* One column per reading type, so the whole set stays on one row.
     The page script writes --tr-mode-cols from the number of types. */
  grid-template-columns: repeat(var(--tr-mode-cols, 1), minmax(0, 1fr));
  gap: 12px;
  margin: 0 0 4px;
}

.tr-mode-lab {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin: 6px 0 0;
  min-width: 0;
}

.tr-mode-lab-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

.tr-mode-lab-title {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.2;
  color: #fff;
}

.tr-mode-lab-note {
  flex: 1 1 220px;
  min-width: 0;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.45;
  color: var(--tr-text-2);
}

.tr-mode {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  text-align: left;
  width: 100%;
  min-width: 0;
  min-height: 44px;
  padding: 16px 14px 14px;
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  color: var(--tr-text);
  cursor: pointer;
  font: inherit;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  transition: background 0.3s var(--ease-quiet), border-color 0.3s var(--ease-quiet),
    box-shadow 0.3s var(--ease-quiet);
}

.tr-mode > * {
  min-width: 0;
  max-width: 100%;
}

.tr-mode:hover,
.tr-mode:focus-visible {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.22);
  outline: none;
}

.tr-mode[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

.tr-mode[aria-disabled="true"]:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.12);
}

/* Active state: fill, border and glow all engage (AGENTS.md recipe). */
.tr-mode.active {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: #fff;
  box-shadow: 0 0 0 2px var(--accent), 0 0 14px var(--accent-glow);
}

.tr-mode-name {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-gold);
}

.tr-mode.active .tr-mode-name {
  color: #fff;
}

.tr-mode-title {
  font-size: 18px;
  font-weight: 700;
  line-height: 1.25;
  color: #fff;
  overflow-wrap: anywhere;
}

.tr-mode-blurb {
  font-size: 13px;
  font-weight: 400;
  line-height: 1.6;
  color: var(--tr-text-2);
  overflow-wrap: anywhere;
}

/* Pushed to the bottom of the card so the meta line sits on a common
   baseline across a row of cards with different blurb lengths. */
.tr-mode-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: auto;
  padding-top: 10px;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-3);
}

.tr-mode-meta span + span::before {
  content: '·';
  margin-right: 6px;
}

/* ============================================================
   6. Fields
   ============================================================ */

.tr-field {
  margin: 0 0 18px;
  min-width: 0;
}

.tr-field:last-child {
  margin-bottom: 0;
}

.tr-hint {
  font-size: 12px;
  line-height: 1.5;
  color: var(--tr-text-3);
  margin: 8px 0 0;
  overflow-wrap: anywhere;
}

/* Stepper for the custom card count. Tightly coupled, so it does not wrap. */
.tr-stepper {
  display: inline-flex;
  align-items: center;
  gap: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--tr-r1);
  background: rgba(255, 255, 255, 0.06);
  overflow: hidden;
}

.tr-stepper button {
  -webkit-appearance: none;
  appearance: none;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.04);
  border: none;
  color: var(--tr-text);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.tr-stepper button:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.1);
}

.tr-stepper button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.tr-stepper output {
  min-width: 56px;
  padding: 0 6px;
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  color: #fff;
}

/* --- Landing globe (tarot-globe.js) ---------------------------------
   CSS 3D so the compositor animates it like the sky: it keeps turning
   while the page scrolls and runs no script per frame. Nothing in the
   preserve-3d chain may set opacity, filter or overflow, or it flattens. */
.tr-globe {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: var(--layout-sidebar-width, 0px);
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
  -webkit-perspective: var(--tr-globe-perspective, 800px);
  perspective: var(--tr-globe-perspective, 800px);
  -webkit-perspective-origin: 50% 50%;
  perspective-origin: 50% 50%;
}

.tr-globe[hidden],
.tarot-page.is-reading .tr-globe {
  display: none;
}

.tr-globe-spin {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
}

.tr-globe-card {
  position: absolute;
  top: calc(var(--tr-globe-h, 36px) / -2);
  left: calc(var(--tr-globe-w, 21px) / -2);
  width: var(--tr-globe-w, 21px);
  height: var(--tr-globe-h, 36px);
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
}

.tr-globe-fly,
.tr-globe-pop {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
}

.tr-globe-face,
.tr-globe-back {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
  box-sizing: border-box;
  object-fit: cover;
  border-radius: 10% / 5.7%;
  /* The near-white card stock the WebGL cards show at their edge
     (tarot-card3d.js edgeMaterial), so the globe matches every other phase.
     About the WebGL card's thickness against its width. */
  border: 1px solid #f0f0f0;
  border-width: max(1px, calc(var(--tr-globe-w, 21px) * 0.045));
  background-color: #f0f0f0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  -webkit-user-select: none;
  user-select: none;
}

.tr-globe-back {
  -webkit-transform: rotateY(180deg);
  transform: rotateY(180deg);
}

/* Each card is born out in the dark and flies onto the sphere. The
   delay and duration are per card, set inline by tarot-globe.js. */
.tr-globe.is-playing .tr-globe-fly {
  -webkit-animation: trGlobeFly 1s cubic-bezier(0.33, 1, 0.68, 1) both;
  animation: trGlobeFly 1s cubic-bezier(0.33, 1, 0.68, 1) both;
}

.tr-globe.is-playing .tr-globe-pop {
  -webkit-animation: trGlobePop 1s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  animation: trGlobePop 1s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* 0.14 rad/s, the WebGL orbit's speed. Starts once the last card lands. */
.tr-globe.is-playing .tr-globe-spin {
  -webkit-animation: trGlobeSpin 44.88s linear infinite both;
  animation: trGlobeSpin 44.88s linear infinite both;
}

@-webkit-keyframes trGlobeFly {
  0% { -webkit-transform: var(--tr-fly-from); visibility: hidden; }
  0.1% { visibility: visible; }
  100% { -webkit-transform: none; visibility: visible; }
}

@keyframes trGlobeFly {
  0% { transform: var(--tr-fly-from); visibility: hidden; }
  0.1% { visibility: visible; }
  100% { transform: none; visibility: visible; }
}

@-webkit-keyframes trGlobePop {
  from { -webkit-transform: scale(0.25); }
  to { -webkit-transform: none; }
}

@keyframes trGlobePop {
  from { transform: scale(0.25); }
  to { transform: none; }
}

@-webkit-keyframes trGlobeSpin {
  from { -webkit-transform: rotateY(0deg); }
  to { -webkit-transform: rotateY(-360deg); }
}

@keyframes trGlobeSpin {
  from { transform: rotateY(0deg); }
  to { transform: rotateY(-360deg); }
}

/* --- Glass cost over a moving field ---------------------------------
   The sky and the globe move behind the panels, so every backdrop blur
   reruns on every frame, at a cost that grows with the screen's pixels.
   A button or row inside a panel already sits on frosted glass; blurring
   it again changes nothing you can see and costs another full pass. */
.tr-panel .tr-btn,
.tr-panel .tr-logrow {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ============================================================
   7. The 3D stage — full-bleed inside the sidebar layout
   ============================================================ */

.tr-stage {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: var(--layout-sidebar-width, 0px);
  width: auto;
  height: auto;
  margin: 0;
  border: 0;
  border-radius: 0;
  z-index: 2;
  /* Transparent: the .tr-void sky shows through the canvas. */
  background: transparent;
  overflow: hidden;
  /* The canvas is dragged; the browser keeps panning for everything else. */
  touch-action: pan-x pan-y;
  overscroll-behavior: none;
}

.tr-stage.is-hidden {
  display: none;
}

/* Landing globe. The column and its glass panels stay above it (they
   carry their own z-index); pointers fall through so the log list, the
   guide and the page scroll keep working while the cards turn.
   The extra classes beat the phone rule that pins .tr-stage at z-index 2,
   which would paint the globe over the panels. */
.tarot-page .main-content .tr-stage.is-ambient {
  z-index: 1;
  pointer-events: none;
}

.tr-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.tr-stage.is-grabbable .tr-canvas {
  cursor: grab;
}

.tr-stage.is-dragging .tr-canvas {
  cursor: grabbing;
}

/* The reading carousel is dragged sideways; vertical swipes stay the page's. */
.tr-stage.is-carousel .tr-canvas {
  touch-action: pan-y;
  cursor: grab;
}

/* Every fixed in-stage layer shares the stage's box so the sidebar keeps
   acting as the left edge. */
.tr-scrim,
.tr-stage-layer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: var(--layout-sidebar-width, 0px);
  pointer-events: none;
}

.tarot-page:not(.is-reading) .tr-scrim,
.tarot-page:not(.is-reading) .tr-stage-layer,
.tarot-page:not(.is-reading) .tr-tracker,
.tarot-page:not(.is-reading) .tr-topbar,
.tarot-page:not(.is-reading) .tr-back {
  display: none;
}

.tr-scrim {
  z-index: 3;
  background: rgba(0, 0, 0, 0.15);
  opacity: 1;
  transition: opacity 0.95s var(--ease-quiet);
}

.tr-scrim.is-lifted {
  opacity: 0;
}

/* Screen-reader copy of the tracker's state. */
.tr-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  -webkit-clip-path: inset(50%);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Status tracker: a small pill at the top of the stage ----------- */

.tr-tracker {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top, 0px));
  left: var(--layout-sidebar-width, 0px);
  right: 0;
  z-index: 1002;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 0 16px;
  box-sizing: border-box;
  pointer-events: none;
  min-width: 0;
}

.tr-tracker-steps {
  list-style: none;
  margin: 0;
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 6px;
  box-sizing: border-box;
  max-width: 100%;
  background: rgba(17, 26, 34, 0.18);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: var(--tr-pill);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-tracker-steps {
    background: rgba(17, 26, 34, 0.62);
  }
}

.tr-tracker-steps li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--tr-text-4);
  transition: color 0.3s var(--ease-quiet);
}

.tr-tracker-steps li::before {
  content: '';
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border: 1px solid currentColor;
  border-radius: 50%;
  box-sizing: border-box;
}

.tr-tracker-steps li.is-done {
  color: var(--tr-text-3);
}

.tr-tracker-steps li.is-done::before {
  background: currentColor;
}

.tr-tracker-steps li.is-current {
  color: var(--tr-text);
}

.tr-tracker-steps li.is-current::before {
  background: var(--tr-gold);
  border-color: var(--tr-gold);
  box-shadow: 0 0 8px rgba(var(--tr-gold-rgb), 0.8);
}

.tr-tracker-hint {
  padding: 4px 12px;
  border-radius: var(--tr-pill);
  background: rgba(17, 26, 34, 0.55);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-3);
  text-shadow: 0 0 12px rgba(0, 0, 0, 0.9);
  text-align: center;
  max-width: min(440px, calc(100vw - 32px));
  overflow-wrap: anywhere;
}

.tr-tracker-hint:empty {
  display: none;
}

/* Shown once every card of the draw is chosen. The tracker itself does
   not take clicks; this button does. */
/* --- Top-right actions ---------------------------------------------- */

.tr-topbar {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top, 0px));
  right: calc(16px + env(safe-area-inset-right, 0px));
  z-index: 1003;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Return to the page's main view, mirrored opposite the topbar. */
.tr-back {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top, 0px));
  left: calc(var(--layout-sidebar-width, 0px) + 16px + env(safe-area-inset-left, 0px));
  z-index: 1003;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.tr-back-icon {
  flex: none;
  display: block;
}

.tr-topbar .tr-btn,
.tr-back.tr-btn {
  height: 40px;
  min-height: 40px;
  padding: 0 18px;
  font-size: 11px;
}

.tr-topbar .tr-btn-quiet,
.tr-back.tr-btn-quiet {
  background: rgba(17, 26, 34, 0.35);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-color: rgba(255, 255, 255, 0.2);
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-topbar .tr-btn-quiet,
  .tr-back.tr-btn-quiet {
    background: rgba(17, 26, 34, 0.62);
  }
}

/* Save only means something once the cards are up. One id outranks the
   [data-tr-auth="required"] reveal rule in section 11. */
.tarot-page:not(.is-revealed) #trSave,
.tarot-page:not(.is-revealed) #trReroll,
#trReroll[hidden] {
  display: none;
}

/* ============================================================
   8. Card captions, projected from the 3D cards
   ============================================================ */

.tr-anchors {
  z-index: 1000;
  overflow: hidden;
}

.tr-anchor {
  position: absolute;
  -webkit-transform: translate(-50%, 0);
  transform: translate(-50%, 0);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: max-content;
  max-width: min(240px, 44vw);
  padding: 12px 12px 4px;
  box-sizing: border-box;
  text-align: center;
  opacity: 0;
  transition: opacity 0.4s var(--ease-quiet);
  text-shadow: 0 0 16px rgba(0, 0, 0, 0.85), 0 1px 4px rgba(0, 0, 0, 0.9);
}

.tr-anchor.is-visible {
  opacity: 1;
}

/* A clicked card is in front of everything; its neighbours' captions
   would float over it. */
.tr-anchors.is-hidden .tr-anchor {
  opacity: 0;
  pointer-events: none;
}

.tr-anchor > * {
  min-width: 0;
  max-width: 100%;
  overflow-wrap: break-word;
  word-break: normal;
}

.tr-anchor-name,
.tr-anchor-orientation,
.tr-resolve {
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.tr-anchor-numeral,
.tr-anchor-name,
.tr-browse-numeral,
.tr-browse-name {
  font-family: 'Birmingham', 'Times New Roman', serif;
  font-weight: 700;
  color: #fff;
}

.tr-anchor-numeral,
.tr-browse-numeral {
  font-size: 13px;
  letter-spacing: 0.16em;
  line-height: 1.2;
  text-align: center;
}

.tr-anchor-numeral[hidden],
.tr-browse-numeral[hidden] {
  display: none;
}

.tr-anchor-name {
  font-size: 18px;
  line-height: 1.2;
  min-height: calc(1.2em * 2);
  max-height: calc(1.2em * 2);
}

.tr-anchor-orientation {
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1.3;
  min-height: calc(1.3em * 2);
  max-height: calc(1.3em * 2);
  text-align: center;
  text-transform: uppercase;
  color: var(--tr-text-2);
}

.tr-anchor.is-reversed .tr-anchor-orientation {
  color: var(--accent);
}

/* Custom faces have no printed rules, so the effect sits in a box under
   the name. FFG majors already carry the text on the card. */
.tr-anchor-effect,
.tr-effect,
.tr-browse-effect {
  box-sizing: border-box;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: rgba(17, 26, 34, 0.18);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
  color: #fff;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  overflow: visible;
  -webkit-animation: tr-effect-in 0.45s ease-out both;
  animation: tr-effect-in 0.45s ease-out both;
}

@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .tr-anchor-effect,
  .tr-effect,
  .tr-browse-effect {
    background: rgba(17, 26, 34, 0.62);
  }
}

@-webkit-keyframes tr-effect-in {
  from { opacity: 0; -webkit-transform: translateY(6px); transform: translateY(6px); }
  to { opacity: 1; -webkit-transform: none; transform: none; }
}

@keyframes tr-effect-in {
  from { opacity: 0; -webkit-transform: translateY(6px); transform: translateY(6px); }
  to { opacity: 1; -webkit-transform: none; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .tr-anchor-effect,
  .tr-effect,
  .tr-browse-effect {
    -webkit-animation: none;
    animation: none;
  }
}

/* While choosing, a box shows both effects under small labels. */
.tr-effect-side {
  display: block;
  margin: 0 0 2px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tr-text-2);
}

.tr-effect-part {
  display: block;
  -webkit-transition: opacity 0.3s ease;
  transition: opacity 0.3s ease;
}

.tr-effect-part + .tr-effect-part {
  margin-top: 8px;
}

.tr-effect-part.is-off {
  opacity: 0.5;
}

.tr-effect-side.is-reverse {
  color: #e5a29b;
}

/* Full height: the spread makes room for the tallest box, so no scroll. */
.tr-anchor-effect {
  display: block;
  width: 100%;
  margin-top: 2px;
  padding: 8px 10px;
  font-size: 12.5px;
  pointer-events: auto;
  /* Narrow phone columns break long words at a syllable, not mid-letter. */
  -webkit-hyphens: auto;
  hyphens: auto;
}

@media (max-width: 932px) {
  .tr-anchor-effect {
    padding: 7px 8px;
    font-size: 11.5px;
  }
}

.tr-anchor-effect[hidden] {
  display: none;
}

/* Sized to the card in JS, so it may be wider than the name above it. */
.tr-anchor > .tr-anchor-effect {
  flex: none;
  max-width: calc(100vw - 16px);
}

.tr-anchors.is-settling .tr-anchor-effect {
  visibility: hidden;
  -webkit-animation: none;
  animation: none;
}

.tr-effect,
.tr-browse-effect {
  font-size: 14px;
}

.tr-effect {
  position: fixed;
  z-index: 1002;
  left: calc(var(--layout-sidebar-width, 0px) + 16px);
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  width: min(560px, calc(100vw - var(--layout-sidebar-width, 0px) - 32px));
  margin: 0 auto;
  padding: 12px 14px;
  pointer-events: auto;
}

.tr-effect[hidden],
.tr-browse-effect[hidden] {
  display: none;
}

.tr-browse-effect {
  width: min(440px, 100%);
  max-width: 100%;
  padding: 10px 12px;
  pointer-events: auto;
}

/* Grand Tableau: take a player who is not at the table out of the reading. */
.tr-anchor > .tr-remove {
  display: -webkit-inline-box;
  display: -webkit-inline-flex;
  display: inline-flex;
  -webkit-box-align: center;
  -webkit-align-items: center;
  align-items: center;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
  pointer-events: auto;
  cursor: pointer;
}

.tr-remove .icon-trash {
  -webkit-flex: none;
  flex: none;
}

.tr-anchor.is-dormant .tr-anchor-orientation {
  color: var(--tr-text-3);
}

.tr-resolve {
  -webkit-appearance: none;
  appearance: none;
  height: calc(1.2em * 2 + 12px);
  min-height: calc(1.2em * 2 + 12px);
  max-height: calc(1.2em * 2 + 12px);
  margin-top: 2px;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(17, 26, 34, 0.55);
  color: #fff;
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.2;
  text-transform: uppercase;
  cursor: pointer;
  pointer-events: auto;
}

.tr-resolve.is-on {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  box-shadow: 0 0 0 2px var(--accent), 0 0 14px var(--accent-glow);
}

.tr-resolve:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Above the WebGL stage (z-index 2) and the scrim, with the captions.
   Without this the portraits paint behind the canvas and never show. */
.tr-portraits {
  z-index: 1001;
}

.tr-portraits.is-hidden {
  opacity: 0;
}

.tr-portrait {
  position: absolute;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.85);
  background: rgba(17, 26, 34, 0.72);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
  -webkit-transform: translate(-50%, -58%);
  transform: translate(-50%, -58%);
  overflow: hidden;
  pointer-events: none;
  /* Same face window the campaign log uses on investigator cards. */
  --fx: 23%;
  --fy: 32%;
  --zoom: 1.9;
}

.tr-portrait img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: cover;
  -o-object-fit: cover;
  object-position: var(--fx) var(--fy);
  -webkit-transform: scale(var(--zoom));
  transform: scale(var(--zoom));
  -webkit-transform-origin: var(--fx) var(--fy);
  transform-origin: var(--fx) var(--fy);
}

.tr-portrait.is-letter::before {
  content: attr(data-letter);
  display: block;
  line-height: 54px;
  text-align: center;
  color: #fff;
  font-weight: 700;
  font-size: 20px;
}

.tr-portrait-mark {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  opacity: 0;
}

.tr-portrait.is-used {
  box-shadow: 0 0 0 2px var(--accent), 0 6px 16px rgba(0, 0, 0, 0.45);
}

.tr-portrait.is-used .tr-portrait-mark {
  opacity: 1;
}

.tr-portrait.is-spawn {
  -webkit-animation: trPortraitIn 0.45s cubic-bezier(0.33, 1, 0.68, 1) both;
  animation: trPortraitIn 0.45s cubic-bezier(0.33, 1, 0.68, 1) both;
}

@-webkit-keyframes trPortraitIn {
  from { opacity: 0; -webkit-transform: translate(-50%, -58%) scale(0.6); }
  to { opacity: 1; -webkit-transform: translate(-50%, -58%) scale(1); }
}

@keyframes trPortraitIn {
  from { opacity: 0; transform: translate(-50%, -58%) scale(0.6); }
  to { opacity: 1; transform: translate(-50%, -58%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .tr-portrait.is-spawn {
    -webkit-animation: trPortraitFade 0.2s ease both;
    animation: trPortraitFade 0.2s ease both;
  }
}

@-webkit-keyframes trPortraitFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes trPortraitFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ============================================================
   9. Choosing reversals (Choice, Destiny, Custom)
   ============================================================
   The caption under each card is the toggle: its orientation line
   becomes a pill that takes the active recipe when reversed. */

.tr-anchor.is-toggle {
  -webkit-appearance: none;
  appearance: none;
  pointer-events: auto;
  min-height: 44px;
  background: none;
  border: 0;
  border-radius: var(--tr-r1);
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.tr-anchor.is-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.tr-anchor.is-toggle .tr-anchor-orientation {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  width: auto;
  min-width: 72px;
  min-height: 28px;
  max-height: none;
  height: auto;
  padding: 4px 12px;
  -webkit-line-clamp: unset;
  text-align: center;
  border-radius: var(--tr-pill);
  background: rgba(17, 26, 34, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.18);
  text-shadow: none;
  transition: background-color 0.3s var(--ease-quiet), border-color 0.3s var(--ease-quiet),
    box-shadow 0.3s var(--ease-quiet);
}

.tr-anchor.is-toggle:hover .tr-anchor-orientation {
  border-color: var(--tr-border-active);
}

.tr-anchor.is-toggle.is-reversed .tr-anchor-orientation {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: #fff;
  box-shadow: 0 0 0 2px var(--accent), 0 0 14px var(--accent-glow);
}

/* Forked Path: a card set to reverse says so with a muted red tint, quiet
   enough to sit beside the upright pills without shouting. */
.tr-anchor .tr-anchor-orientation.is-reverse,
.tr-anchor.is-toggle.is-reversed .tr-anchor-orientation.is-reverse {
  color: #f2b8b2;
}

.tr-anchor.is-toggle.is-reversed .tr-anchor-orientation.is-reverse {
  background: rgba(17, 26, 34, 0.55);
  border-color: rgba(235, 110, 100, 0.45);
  box-shadow: inset 0 0 0 1px rgba(235, 110, 100, 0.12);
}

.tr-anchor.is-toggle.is-reversed:hover .tr-anchor-orientation.is-reverse {
  border-color: rgba(235, 110, 100, 0.7);
}

/* Observed: the caption under each drawn card is the keep button. */
.tr-anchor.is-keep .tr-anchor-orientation {
  border-color: var(--accent-border);
  color: #fff;
}

.tr-anchor.is-keep:hover .tr-anchor-orientation,
.tr-anchor.is-keep:focus-visible .tr-anchor-orientation {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: #fff;
  box-shadow: 0 0 0 2px var(--accent), 0 0 14px var(--accent-glow);
}

/* A caption arrives once, as its card lands face up: the name drifts up
   and fades in on one long ease-out, the orientation line follows.
   Only the two lines animate; the caption box itself stays put while
   tarot-page.js moves it every frame. The class stays on until both
   lines have finished (CAPTION_ENTER_MS), and a caption rebuilt as a
   button mid-entrance resumes where it was through a negative
   animation-delay set on each line. Delays and durations here must
   match CAPTION_ENTER in tarot-page.js. */
.tr-anchor.is-entering {
  -webkit-transition: none;
  transition: none;
}

.tr-anchor.is-entering > .tr-anchor-numeral,
.tr-anchor.is-entering > .tr-anchor-name,
.tr-anchor.is-entering > .tr-anchor-orientation {
  will-change: opacity, transform;
  -webkit-animation-name: trCaptionFade, trCaptionRise;
  animation-name: trCaptionFade, trCaptionRise;
  -webkit-animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1), cubic-bezier(0.33, 1, 0.68, 1);
  animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1), cubic-bezier(0.33, 1, 0.68, 1);
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

.tr-anchor.is-entering > .tr-anchor-numeral,
.tr-anchor.is-entering > .tr-anchor-name {
  -webkit-animation-duration: 1.3s, 1.6s;
  animation-duration: 1.3s, 1.6s;
  -webkit-animation-delay: 0.1s;
  animation-delay: 0.1s;
}

.tr-anchor.is-entering > .tr-anchor-numeral {
  -webkit-animation-delay: 0.04s;
  animation-delay: 0.04s;
}

.tr-anchor.is-entering > .tr-anchor-orientation {
  -webkit-animation-duration: 1s, 1.2s;
  animation-duration: 1s, 1.2s;
  -webkit-animation-delay: 0.5s;
  animation-delay: 0.5s;
}

@-webkit-keyframes trCaptionFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes trCaptionFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@-webkit-keyframes trCaptionRise {
  from { -webkit-transform: translate3d(0, 12px, 0); }
  to { -webkit-transform: translate3d(0, 0, 0); }
}

@keyframes trCaptionRise {
  from { transform: translate3d(0, 12px, 0); }
  to { transform: translate3d(0, 0, 0); }
}

@-webkit-keyframes trFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes trFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Observed on a phone: one drawn card at a time, full size. tarot-page.js
   sets --tr-browse-mid (the card's centre line) and --tr-browse-foot
   (just under its bottom edge) from the 3D card. */
.tr-browse {
  z-index: 1001;
}

.tr-browse[hidden] {
  display: none;
}

.tr-browse-arrow {
  -webkit-appearance: none;
  appearance: none;
  position: absolute;
  /* Centred with a margin, not a transform: mobile-optimized.css gives
     every pressed button transform: scale(0.98), which would drop the
     translateY(-50%) and make the arrow jump half its height on each tap. */
  top: var(--tr-browse-mid, 45%);
  margin-top: -22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  min-height: 44px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(17, 26, 34, 0.45);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  color: #fff;
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
  transition: opacity 0.3s var(--ease-quiet), border-color 0.25s var(--ease-quiet),
    -webkit-transform 0.15s var(--ease-quiet), transform 0.15s var(--ease-quiet);
}

.tr-browse .tr-browse-arrow:active:not(:disabled) {
  -webkit-transform: scale(0.92);
  transform: scale(0.92);
  border-color: rgba(255, 255, 255, 0.4);
}

.tr-browse .tr-browse-arrow:disabled:active {
  -webkit-transform: none;
  transform: none;
}

@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .tr-browse-arrow {
    background: rgba(17, 26, 34, 0.62);
  }
}

.tr-browse-arrow.is-prev {
  left: calc(8px + env(safe-area-inset-left, 0px));
}

.tr-browse-arrow.is-next {
  right: calc(8px + env(safe-area-inset-right, 0px));
}

.tr-browse-arrow:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.tr-browse-arrow:disabled {
  opacity: 0.28;
  cursor: default;
}

.tr-browse-foot {
  position: absolute;
  top: calc(var(--tr-browse-foot, 74%) + 14px);
  left: 16px;
  right: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-width: 0;
  text-align: center;
  pointer-events: none;
}

.tr-browse-numeral {
  margin: 0;
  font-size: 14px;
  letter-spacing: 0.16em;
  line-height: 1.2;
  text-shadow: 0 0 16px rgba(0, 0, 0, 0.85), 0 1px 4px rgba(0, 0, 0, 0.9);
  -webkit-animation: trCaptionFade 1.3s cubic-bezier(0.37, 0, 0.63, 1) 0.04s both,
    trCaptionRise 1.6s cubic-bezier(0.33, 1, 0.68, 1) 0.04s both;
  animation: trCaptionFade 1.3s cubic-bezier(0.37, 0, 0.63, 1) 0.04s both,
    trCaptionRise 1.6s cubic-bezier(0.33, 1, 0.68, 1) 0.04s both;
}

.tr-browse-name {
  margin: 0;
  max-width: 100%;
  min-width: 0;
  font-size: 20px;
  line-height: 1.2;
  overflow-wrap: anywhere;
  text-shadow: 0 0 16px rgba(0, 0, 0, 0.85), 0 1px 4px rgba(0, 0, 0, 0.9);
  -webkit-animation: trCaptionFade 1.3s cubic-bezier(0.37, 0, 0.63, 1) 0.1s both,
    trCaptionRise 1.6s cubic-bezier(0.33, 1, 0.68, 1) 0.1s both;
  animation: trCaptionFade 1.3s cubic-bezier(0.37, 0, 0.63, 1) 0.1s both,
    trCaptionRise 1.6s cubic-bezier(0.33, 1, 0.68, 1) 0.1s both;
}

.tr-browse-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 10px;
  min-width: 0;
}

.tr-browse-dots {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.tr-browse-dot {
  width: 6px;
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.35);
  transition: width 0.3s var(--ease-quiet), background-color 0.3s var(--ease-quiet);
}

.tr-browse-dot.is-current {
  width: 18px;
  background: var(--accent);
}

.tr-browse-count {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-2);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
}

.tr-browse-keep {
  width: min(280px, 100%);
  margin-top: 4px;
  pointer-events: auto;
}

.tr-browse-keep:disabled {
  opacity: 0.4;
  cursor: default;
}

/* A phone on its side has no room above the card for the tracker; the
   count under the card carries where the reader is. */
@media (max-height: 500px) {
  .tarot-page.is-browsing .tr-tracker {
    display: none;
  }
}

/* ============================================================
   10. Past readings
   ============================================================ */

.tr-history {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(min(440px, 100%), 1fr));
  align-items: start;
}

.tr-history-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  min-width: 0;
}

.tr-history-item > * {
  min-width: 0;
}

.tr-history-main {
  flex: 1 1 220px;
  min-width: 0;
}

.tr-history-title {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  margin: 0 0 4px;
  overflow-wrap: anywhere;
}

.tr-history-item.is-pending {
  border-color: rgba(255, 159, 10, 0.55);
}

.tr-history-pending {
  display: block;
  margin-top: 4px;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-warning);
  overflow-wrap: anywhere;
}

.tr-history-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--tr-text-3);
  overflow-wrap: anywhere;
  min-width: 0;
}

.tr-history-meta > span {
  min-width: 0;
}

.tr-history-meta > span + span::before {
  content: '·';
  margin-right: 8px;
  color: var(--tr-text-4);
}

.tr-history-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* "Reading 2" — which of the log's rows this is. */
.tr-history-row {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--tr-pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #fff;
}

.tr-history-cards {
  flex: 1 1 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

/* Which campaign log scenario the row was drawn for. */
.tr-history-scenario {
  display: block;
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--tr-text);
  overflow-wrap: anywhere;
}

/* Card faces; a reversed card lies upside down, as on the table. */
.tr-history-thumb {
  -webkit-appearance: none;
  appearance: none;
  flex: none;
  display: block;
  width: 56px;
  height: 84px;
  padding: 0;
  margin: 0;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.06);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  cursor: zoom-in;
  transition: border-color 0.2s var(--ease-quiet), box-shadow 0.2s var(--ease-quiet);
}

.tr-history-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

.tr-history-thumb.is-reversed img {
  -webkit-transform: rotate(180deg);
  transform: rotate(180deg);
}

.tr-history-thumb.is-reversed {
  border-color: var(--accent-border);
}

.tr-history-thumb.is-inactive img {
  opacity: 0.5;
}

.tr-history-thumb:hover,
.tr-history-thumb:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-glow), 0 2px 8px rgba(0, 0, 0, 0.35);
  outline: none;
}

/* The enlarged card. Sized and placed in JS (showPeek). */
.tr-peek {
  position: fixed;
  z-index: 2147483000;
  left: 0;
  top: 0;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  -webkit-transform: scale(0.35);
  transform: scale(0.35);
  transition: opacity 0.16s ease-out, -webkit-transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s linear 0.2s;
  transition: opacity 0.16s ease-out, transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s linear 0.2s;
}

.tr-peek.is-on {
  opacity: 1;
  visibility: visible;
  -webkit-transform: none;
  transform: none;
  transition: opacity 0.16s ease-out, -webkit-transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s;
  transition: opacity 0.16s ease-out, transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s;
}

.tr-peek-card {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: #0b0f14;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
}

.tr-peek-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.tr-peek.is-reversed .tr-peek-img {
  -webkit-transform: rotate(180deg);
  transform: rotate(180deg);
}

.tr-peek-effect {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  max-height: calc(100% - 16px);
  overflow: hidden;
  box-sizing: border-box;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(17, 26, 34, 0.55);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  backdrop-filter: blur(14px) saturate(180%);
  color: #fff;
  font-size: 12.5px;
  line-height: 1.45;
  text-align: left;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  overflow-wrap: anywhere;
}

@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .tr-peek-effect {
    background: rgba(17, 26, 34, 0.88);
  }
}

.tr-peek-name {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
}

.tr-peek-meta {
  margin: 1px 0 0;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tr-text-2);
}

.tr-peek.is-reversed .tr-peek-meta {
  color: #e5a29b;
}

.tr-peek-text {
  margin-top: 6px;
}

.tr-peek-text[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .tr-peek,
  .tr-peek.is-on {
    -webkit-transform: none;
    transform: none;
  }
}

.tr-history-actions {
  flex: 1 1 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* A row whose reading was deleted: it still counts, and may be rerolled. */
.tr-history-item.is-empty .tr-history-title {
  color: var(--tr-text-2);
  font-style: italic;
}

/* ============================================================
   11. Empty / guest states
   ============================================================ */

.tr-empty {
  padding: 28px 20px;
  text-align: center;
  color: var(--tr-text-2);
  font-size: 14px;
  line-height: 1.7;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  overflow-wrap: anywhere;
}

/* The guest sign-in prompt is a sentence, not a status readout, so it opts
   back out of the boxed empty-state look. */
.tarot-page [data-tr-auth="guest"] .tr-empty {
  background: transparent;
  border: 0;
  padding: 8px 0;
}

.tr-empty .tr-btn {
  margin-top: 16px;
}

/* Auth-gated chrome. Both branches stay hidden until api/auth.php?action=me
   answers and tarot-page.js puts `tr-auth-in` or `tr-auth-out` on the body,
   so neither a guest nor a member sees the wrong one flash first.

   The display value has to be declared per element type here: the previous
   implementation revealed these nodes from JS with `style.display = ''`,
   which *removes* the inline declaration and hands the element straight back
   to the `display: none` rule below — so the Save button, the Past readings
   panel and the guest sign-in prompt never appeared at all. */
[data-tr-auth="required"],
[data-tr-auth="guest"] {
  display: none;
}

.tarot-page.tr-auth-in div[data-tr-auth="required"] {
  display: block;
}

.tarot-page.tr-auth-in button[data-tr-auth="required"],
.tarot-page.tr-auth-in a[data-tr-auth="required"] {
  display: inline-flex;
}

.tarot-page.tr-auth-out div[data-tr-auth="guest"] {
  display: block;
}

/* ============================================================
   12. Breakpoints
   ============================================================
   Control height steps 48 → 44 above the phone breakpoint and stays at
   44 on phones, our tap-target floor. */

@media (max-width: 1280px) {
  .tarot-page { --tr-btn-h: 44px; }
}

/* Between the phone breakpoint and a wide desktop the stage beside the
   sidebar is too narrow for a centred tracker AND the top-right buttons,
   so the tracker moves to the stage's left edge. */
@media (min-width: 933px) and (max-width: 1279px) {
  .tr-tracker {
    align-items: flex-start;
  }
}

@media (max-width: 932px) {
  .tarot-page { --tr-btn-h: 44px; }

  .tr-awake {
    min-height: 44px;
  }

  /* mobile-optimized.css sets z-index:auto on any tapped (:hover/:focus/
     :active) element inside .main-content. That clamp is only (0, 2, 0),
     so a three-class selector keeps the real z-index through the whole
     tap. These layers sit above the sky or the full-screen stage only by
     z-index: without this, the pressed Back / Start over / Save controls
     fall behind the canvas and the tap spins a card instead of navigating.
     They stay under the mobile header (10000). */
  .tarot-page .main-content .tarot-header { z-index: 4999; }
  .tarot-page .main-content .tr-panel { z-index: 1001; }
  .tarot-page .main-content .tr-skins { z-index: 1004; }
  .tarot-page .main-content .tr-picker-panel { z-index: 1; }
  .tarot-page .main-content .tr-back,
  .tarot-page .main-content .tr-topbar { z-index: 1003; }
  .tarot-page .main-content .tr-anchors { z-index: 1000; }
  .tarot-page .main-content .tr-browse { z-index: 1001; }
  .tarot-page .main-content .tr-stage { z-index: 2; }
  .tarot-page .main-content .tr-globe { z-index: 1; }

  /* Once a reading starts the stage owns the whole viewport, so the fixed
     phone header would sit on top of the tracker pill. The stage carries its
     own Back button, which returns to the landing view and the header. */
  .tarot-page.is-reading .mobile-header {
    display: none !important;
  }

  /* The sidebar is off-canvas here and sidebar-layout.css already sets
     --layout-sidebar-width to 0px, but the stage layers are pinned
     explicitly so a stale variable can never inset them. */
  .tr-void,
  .tr-globe,
  .tr-stage,
  .tr-scrim,
  .tr-stage-layer,
  .tr-tracker {
    left: 0;
  }

  .tarot-container {
    padding: 20px 14px 96px;
  }

  .tr-skins {
    left: calc(8px + env(safe-area-inset-left, 0px));
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    max-width: calc(100vw - 84px);
  }

  .tr-panel {
    padding: 18px 16px;
  }

  .tarot-page .tr-picker {
    padding: 0;
  }

  .tarot-page .tr-picker-panel {
    width: 100%;
    max-width: none;
    max-height: 100%;
    height: 100%;
    border-radius: 0 !important;
  }

  .tr-read-head {
    padding: calc(18px + env(safe-area-inset-top, 0px)) 18px 16px;
  }

  .tarot-page .tr-picker-panel h2.tr-picker-title {
    font-size: 20px;
  }

  .tr-read-body {
    padding: 18px;
  }

  /* The site-wide bug-report FAB sits over the bottom-right corner of the
     full-screen popup, so the footer keeps clear of it. */
  .tr-read-foot {
    padding: 14px 18px calc(14px + env(safe-area-inset-bottom, 0px));
    justify-content: flex-start;
  }

  .tr-read-foot .tr-btn {
    flex: 1 1 auto;
  }

  .tr-read-head-actions {
    flex: 1 1 100%;
  }

  .tr-read-head-actions .tr-btn {
    width: 100%;
  }

  .tr-modes {
    grid-template-columns: 1fr;
  }

  /* Buttons take the top row, one line beside the Back button; the
     tracker sits under them. */
  .tr-topbar {
    top: calc(10px + env(safe-area-inset-top, 0px));
    right: calc(10px + env(safe-area-inset-right, 0px));
    left: calc(64px + env(safe-area-inset-left, 0px));
    flex-wrap: nowrap;
    gap: 6px;
  }

  .tr-topbar .tr-btn {
    flex: 0 1 auto;
    min-width: 0;
    height: 44px;
    min-height: 44px;
    padding: 0 14px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .tr-topbar .tr-view-delete {
    flex: none;
    width: 44px;
    padding: 0;
    justify-content: center;
  }

  .tr-topbar .tr-label-long {
    display: none;
  }

  .tr-topbar .tr-label-short {
    display: inline;
  }

  /* Icon only, so it never crowds the topbar on a narrow phone. */
  .tr-back.tr-btn {
    top: calc(10px + env(safe-area-inset-top, 0px));
    left: calc(10px + env(safe-area-inset-left, 0px));
    width: 44px;
    height: 44px;
    min-height: 44px;
    padding: 0;
  }

  .tr-back-label {
    display: none;
  }

  .tr-tracker {
    top: calc(64px + env(safe-area-inset-top, 0px));
    padding: 0 10px;
  }

  .tr-anchor {
    max-width: min(160px, 46vw);
    gap: 5px;
    padding: 10px 8px 4px;
  }

  .tr-anchor-numeral {
    font-size: 11px;
    letter-spacing: 0.12em;
  }

  /* Small enough that one-word names (Strength, Temperance) fit a column
     of three on a 375px phone without breaking mid-word. */
  .tr-anchor-name {
    font-size: 13.5px;
  }

  .tr-anchor-orientation {
    font-size: 10px;
    letter-spacing: 0.03em;
  }

  .tr-effect {
    left: calc(8px + env(safe-area-inset-left, 0px));
    right: calc(8px + env(safe-area-inset-right, 0px));
    width: auto;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  }

  .tr-resolve {
    height: 44px;
    min-height: 44px;
    max-height: 44px;
    padding: 4px 12px;
  }

  .tr-portrait {
    width: 48px;
    height: 48px;
  }

  .tr-portrait.is-letter::before {
    line-height: 44px;
    font-size: 18px;
  }

}

@media (max-width: 560px) {
  .tr-logpager {
    justify-content: center;
  }

  .tr-logrow {
    gap: 12px 14px;
  }

  .tr-logrow-art {
    width: 96px;
    height: 64px;
  }

  .tr-logrow-art.is-card,
  .tr-read-art.is-card,
  .tr-logrow-art.is-stack,
  .tr-read-art.is-stack {
    width: 64px;
    height: 91px;
  }

  .tr-logrow-body {
    flex-basis: 140px;
  }

  /* Meta lines wrap here, and a separator would start the next line. */
  .tr-logrow-meta,
  .tr-read-meta {
    gap: 2px 12px;
  }

  .tr-logrow-meta > span + span::before,
  .tr-read-meta > span + span::before {
    content: none;
  }

  .tr-logrow-action {
    flex: 1 1 100%;
  }

  .tr-logrow-action .tr-btn {
    width: 100%;
  }
}

/* Very narrow phones: 320px must not overflow. */
@media (max-width: 400px) {
  .tr-btn {
    padding: 0 16px;
    letter-spacing: 0.03em;
  }

  .tr-logrow-art,
  .tr-read-art {
    width: 72px;
    height: 48px;
  }

  .tr-logrow-name {
    font-size: 15.5px;
  }

  .tr-eyebrow {
    letter-spacing: 0.03em;
  }

  .tr-stepper button {
    width: 44px;
  }

  .tr-tracker-steps {
    padding: 0 3px;
  }

  .tr-tracker-steps li {
    gap: 5px;
    padding: 0 7px;
    letter-spacing: 0.03em;
  }

  .tr-topbar .tr-btn {
    padding: 0 12px;
    letter-spacing: 0.03em;
  }
}

/* ============================================================
   12b. The reading popup on phones
   ============================================================
   Full screen, so every pixel of height goes to the reading types: the
   head is one compact row (small art, title, a short Close / Switch
   button), the types tile into as many columns as fit, and the footer
   stays one row. Placed after the width blocks above so it wins. */

@media (max-width: 932px) {
  /* The popup lives inside .main-content's stacking context, so no
     z-index lifts it over the site's phone header, which would cover its
     title. The full-screen popup has its own Close, so the header steps
     aside while it is open, as it does during a reading. */
  .tarot-page.modal-open .mobile-header {
    display: none !important;
  }

  .tr-read-head {
    flex-wrap: nowrap;
    gap: 12px;
    padding: calc(12px + env(safe-area-inset-top, 0px)) calc(12px + env(safe-area-inset-right, 0px))
      12px calc(16px + env(safe-area-inset-left, 0px));
  }

  .tr-read-art,
  .tr-read-art.is-back {
    flex: none;
    width: 60px;
    height: 40px;
  }

  .tr-read-art.is-card,
  .tr-read-art.is-stack {
    flex: none;
    width: 40px;
    height: 57px;
  }

  .tr-read-heading {
    flex: 1 1 auto;
  }

  .tr-read-heading .tr-eyebrow {
    margin-bottom: 2px;
  }

  .tarot-page .tr-picker-panel h2.tr-picker-title {
    font-size: 18px;
    line-height: 1.2;
    overflow-wrap: anywhere;
  }

  .tr-read-meta {
    margin-top: 3px;
  }

  .tr-read-head-actions {
    flex: none;
    align-self: flex-start;
  }

  .tr-read-head-actions .tr-btn {
    width: auto;
    padding: 0 14px;
    white-space: nowrap;
  }

  .tr-read-head-actions .tr-label-long {
    display: none;
  }

  .tr-read-head-actions .tr-label-short {
    display: inline;
  }

  .tr-read-body {
    padding: 14px calc(16px + env(safe-area-inset-right, 0px)) 18px calc(16px + env(safe-area-inset-left, 0px));
  }

  .tr-modes {
    grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
    gap: 10px;
  }

  .tr-mode {
    gap: 5px;
    padding: 14px 16px 12px;
  }

  .tr-mode-title {
    font-size: 17px;
  }

  .tr-mode-blurb {
    line-height: 1.5;
  }

  .tr-mode-meta {
    padding-top: 6px;
  }

  .tr-read-history {
    margin-top: 20px;
    padding-top: 16px;
  }

  .tr-read-foot {
    flex-wrap: nowrap;
    gap: 12px;
    padding: 12px calc(16px + env(safe-area-inset-right, 0px)) calc(12px + env(safe-area-inset-bottom, 0px))
      calc(16px + env(safe-area-inset-left, 0px));
  }

  .tr-read-foot .tr-count {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 46%;
    line-height: 1.35;
    overflow-wrap: anywhere;
    text-wrap: balance;
  }

  .tr-read-foot .tr-btn {
    flex: 1 1 0;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* A phone on its side: drop everything in the head but the title and the
   button, so the types still get most of the height. */
@media (max-width: 932px) and (max-height: 500px) {
  .tr-read-head {
    padding-top: calc(8px + env(safe-area-inset-top, 0px));
    padding-bottom: 8px;
  }

  .tr-read-art,
  .tr-read-heading .tr-eyebrow,
  .tr-read-meta {
    display: none;
  }

  .tr-read-head-actions {
    align-self: center;
  }

  .tr-read-body {
    padding-top: 10px;
  }

  .tr-mode-blurb {
    font-size: 12.5px;
  }

  .tr-read-foot {
    padding-top: 8px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  }
}

/* ============================================================
   13. Motion preferences
   ============================================================
   Individual animations and transitions are switched off; there is
   deliberately no universal duration clamp at any scope (AGENTS.md). */

@media (prefers-reduced-motion: reduce) {
  .tr-void-sky,
  .tr-void-twinkle {
    -webkit-animation: none;
    animation: none;
  }

  .tr-void-drift,
  .tarot-page.tr-sky-swirl .tr-void-drift {
    -webkit-transition: none;
    transition: none;
  }

  .tr-void,
  .tr-mode,
  .tr-mode::before,
  .tr-btn,
  .tr-icon-btn,
  .tr-anchor,
  .tr-scrim,
  .tr-logrow,
  .tr-tracker-steps li,
  .tarot-page .tr-picker {
    transition: none;
  }

  .tr-btn.is-loading::after {
    animation: none;
  }

  .tr-anchor.is-entering > .tr-anchor-numeral,
  .tr-anchor.is-entering > .tr-anchor-name,
  .tr-anchor.is-entering > .tr-anchor-orientation,
  .tr-browse-numeral,
  .tr-browse-name {
    -webkit-animation: trFadeIn 0.3s linear both;
    animation: trFadeIn 0.3s linear both;
  }

  .tr-browse-arrow,
  .tr-browse-dot {
    transition: none;
  }
}
