/* ============================================================
   Kelvin — built on the BTF "cosmic crystal" design system.
   Same void, same crystal stone, same metals, same type pairing.
   The one thing Kelvin adds is meaning: the palette's warm-to-cool
   run (burn → gold → silver → stone-2 → stone) is the thermal
   scale, so colour here is data, not decoration.
   ============================================================ */

:root {
  /* void / atmosphere */
  --void:      #0a0712;
  --void-2:    #140b22;
  --void-3:    #1c0f33;

  /* crystal stone */
  --stone:     #7b44bd;
  --stone-2:   #b27ee8;
  --stone-deep:#2a1640;

  /* metals + ember */
  --gold:      #e9c87d;
  --gold-hi:   #fff3cf;
  --silver:    #d7dcec;
  --burn:      #ff5a3c;

  /* ink */
  --fg:        #ece6f7;
  --muted:     #9a8fb8;
  --hair:      rgba(202,166,239,0.22);

  --display: "Cinzel", "Trajan Pro", Georgia, serif;
  --body:    "EB Garamond", Georgia, "Times New Roman", serif;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --r: 10px;
}

* { box-sizing: border-box; }

html, body { margin: 0; }

body {
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  color: var(--fg);
  background: var(--void);
  /* atmosphere: starfield dots layered over a deep nebula wash */
  background-image:
    radial-gradient(2px 2px at 18% 24%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.5px 1.5px at 72% 16%, rgba(255,255,255,0.7), transparent 60%),
    radial-gradient(1.5px 1.5px at 38% 72%, rgba(231,225,255,0.6), transparent 60%),
    radial-gradient(1px 1px at 86% 64%, rgba(255,255,255,0.75), transparent 60%),
    radial-gradient(1px 1px at 8% 82%, rgba(255,255,255,0.6), transparent 60%),
    radial-gradient(1.5px 1.5px at 58% 44%, rgba(255,255,255,0.5), transparent 60%),
    radial-gradient(ellipse 80% 60% at 50% 18%, rgba(123,68,189,0.20), transparent 70%),
    radial-gradient(ellipse 70% 70% at 78% 88%, rgba(63,31,108,0.30), transparent 70%),
    linear-gradient(160deg, var(--void), var(--void-2) 60%, var(--void-3));
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

/* grain overlay — adds tooth so the dark never reads as flat */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.container {
  max-width: 60rem;
  margin: 0 auto;
  padding: clamp(1.5rem, 4vh, 3rem) clamp(1rem, 4vw, 2rem) 4rem;
  /* NB: no transform/animation here. A transformed ancestor becomes the
     containing block for position:fixed descendants, which would break the
     Recipes tab and the browser overlay. Animate the header instead. */
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   Header — the mark, then the scale
   ============================================================ */
.head {
  text-align: center;
  margin-bottom: clamp(2rem, 5vh, 3rem);
  animation: rise 0.7s var(--ease) both;
}

.head__sigil {
  width: auto;
  height: clamp(96px, 20vw, 150px);
  display: block;
  margin: 0 auto 0.75rem;
  filter: drop-shadow(0 0 24px rgba(123,68,189,0.55));
}

.head__mark {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(2.25rem, 8vw, 3.5rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 0;
  background: linear-gradient(100deg, var(--burn), var(--gold) 30%, var(--silver) 55%, var(--stone-2) 80%, var(--stone));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.head__hint {
  margin: 0 0 1rem;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-family: var(--display);
  color: var(--muted);
  opacity: 0.75;
}

.head__tag {
  margin: 0.35rem 0 0.6rem;
  color: var(--muted);
  font-size: 1.0625rem;
  font-style: italic;
}

.scale {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;                      /* must match .pattern__span, or the tree drifts */
  list-style: none;
  margin: 0; padding: 0;
  border: 1px solid var(--hair);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--hair);
}

.scale > li { display: flex; }

.scale__stop {
  flex: 1;
  border: 0;
  border-radius: 0;
  font-family: inherit;
  color: var(--fg);
  cursor: pointer;
  transition: filter 0.2s var(--ease);
  padding: 0.7rem 0.35rem;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--swatch) 20%, var(--stone-deep)),
    color-mix(in srgb, var(--swatch) 6%, var(--void-2)));
  border-top: 2px solid var(--swatch);
  display: flex; flex-direction: column; align-items: center; gap: 0.05rem;
}

.scale__stop:hover { filter: brightness(1.35); }
.scale__stop:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.scale__stop[aria-pressed="true"] { filter: brightness(1.5); }

.scale__hanzi { font-family: var(--display); font-size: 1.3rem; color: var(--swatch); line-height: 1.2; }
.scale__name  { font-family: var(--display); font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; }
.scale__k     { font-size: 0.8125rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ============================================================
   Pickers
   ============================================================ */
.pick { border: 0; padding: 0; margin: 0 0 2rem; }

.pick__legend {
  font-family: var(--display);
  font-size: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
  padding: 0;
  margin-bottom: 0.9rem;
}

.ratchet  { display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); gap: 0.6rem; }
.patterns { display: grid; gap: 0.4rem; }

.tier {
  display: flex; flex-direction: column; gap: 0.15rem;
  text-align: left;
  padding: 0.9rem 1rem;
  background: linear-gradient(180deg, rgba(42,22,64,0.55), rgba(20,11,34,0.75));
  border: 1px solid var(--hair);
  border-radius: var(--r);
  color: var(--fg);
  font-family: var(--body); font-size: 1rem;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), transform 0.12s var(--ease);
}

/* ── the selector, drawn as one tree ──────────────────────────────────────
   The scale and every pattern share the same five columns, so a band visibly
   spans the natures it covers. That relationship used to be invisible: five
   natures beside five patterns reads as a 1:1 map, and it isn't — three of
   them contain warm. */
.pattern {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.45rem;
  text-align: left;
  /* No horizontal padding: the span strip has to occupy the same box as the
     scale above it or the columns do not line up, and a tree that almost lines
     up reads worse than one that obviously doesn't. Padding lives on the body. */
  padding: 0 0 0.7rem;
  background: linear-gradient(180deg, rgba(42,22,64,0.5), rgba(20,11,34,0.7));
  border: 1px solid var(--hair);
  border-radius: var(--r);
  color: var(--fg);
  font-family: var(--body); font-size: 1rem;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}

/* the span strip — same 5 columns and gap as .scale above it */
.pattern__span {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;                      /* must match .scale */
  border-radius: var(--r) var(--r) 0 0;
  overflow: hidden;
}
.pattern__span i {
  height: 8px;
  background: var(--hair);
  transition: background 0.25s var(--ease);
}
.pattern__span i.is-lit { background: var(--c); }

.pattern__body {
  display: flex; flex-direction: column; gap: 0.1rem;
  padding: 0 0.85rem;
}
.pattern__q {
  font-size: 0.9375rem; color: var(--fg);
}
.pattern__name {
  font-family: var(--display); font-size: 0.65rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
}

.tier:hover:not(:disabled), .pattern:hover {
  border-color: rgba(233,200,125,0.45);
  box-shadow: 0 0 22px rgba(123,68,189,0.28);
}
.tier:active:not(:disabled), .pattern:active { transform: translateY(1px); }

.tier[aria-pressed="true"], .pattern[aria-pressed="true"] {
  border-color: var(--gold);
  box-shadow: 0 0 26px rgba(233,200,125,0.22), inset 0 0 40px rgba(123,68,189,0.22);
}

.tier:disabled { opacity: 0.35; cursor: not-allowed; }

/* a nature was tapped on the scale: these patterns reach it. Distinct from
   [aria-pressed] — this is "these qualify", not "this is chosen". */
.pattern--match {
  border-color: var(--stone-2);
  box-shadow: 0 0 26px rgba(178,126,232,0.35);
}
.pattern--dim { opacity: 0.4; }

.tier__step {
  font-family: var(--display); font-size: 0.6875rem;
  letter-spacing: 0.18em; color: var(--muted);
}
.tier__name {
  font-family: var(--display); font-size: 1.0625rem;
  letter-spacing: 0.06em; color: var(--gold-hi);
}
.tier__meta  { font-size: 0.9375rem; color: var(--muted); }
.tier__stock { font-size: 0.8125rem; color: var(--muted); opacity: 0.7; font-style: italic; }

.pattern__caution { font-size: 0.78rem; color: var(--burn); opacity: 0.8; font-style: italic; }
.pattern[aria-pressed="true"] .pattern__q { color: var(--gold-hi); }

.pick__hint {
  margin: -0.4rem 0 0.8rem; font-size: 0.8125rem;
  color: var(--muted); font-style: italic;
}

.roll-btn {
  width: 100%;
  padding: 1rem;
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--void);
  background: linear-gradient(100deg, var(--gold), var(--gold-hi) 55%, var(--gold));
  border: 0; border-radius: var(--r);
  cursor: pointer;
  box-shadow: 0 0 30px rgba(233,200,125,0.28);
  transition: box-shadow 0.25s var(--ease), transform 0.12s var(--ease);
}
.roll-btn:hover  { box-shadow: 0 0 44px rgba(233,200,125,0.5); }
.roll-btn:active { transform: translateY(1px); }

/* ============================================================
   The table
   ============================================================ */
.table { margin-top: 2.5rem; }
.table__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.table__title {
  font-family: var(--display); font-size: 1.125rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--gold); margin: 0;
}
.table__hint { color: var(--muted); font-size: 0.9375rem; font-style: italic; margin: 0.35rem 0 1.25rem; }

.ghost {
  background: none; border: 1px solid var(--hair); border-radius: var(--r);
  color: var(--muted); font-family: var(--display); font-size: 0.75rem;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.4rem 0.8rem; cursor: pointer;
}
.ghost:hover { color: var(--gold); border-color: rgba(233,200,125,0.45); }

/* The table. A slot is just a wrapper now — the face inside it is .deckslide,
   the same component the Recipes browser renders, so the two always match. */
.slots { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }

.slot { animation: rise 0.5s var(--ease) both; }
.slot--kept .deckslide {
  border-color: var(--swatch);
  box-shadow: 0 0 30px color-mix(in srgb, var(--swatch) 28%, transparent);
}

/* on the table the face is full width, not a carousel slide */
.slot .deckslide { width: 100%; }

.slot__acts { display: flex; gap: 0.5rem; margin-top: 0.75rem; flex-wrap: wrap; }

.act {
  padding: 0.4rem 0.95rem;
  border-radius: var(--r); border: 1px solid var(--hair);
  background: rgba(42,22,64,0.5); color: var(--fg);
  font-family: var(--display); font-size: 0.75rem;
  letter-spacing: 0.12em; text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.act:hover { border-color: rgba(233,200,125,0.45); color: var(--gold); }
.act--keep[aria-pressed="true"] {
  background: var(--swatch); color: var(--void); border-color: var(--swatch);
}
.act:disabled { opacity: 0.3; cursor: not-allowed; }

/* ============================================================
   Recipe detail
   ============================================================ */
.detail { margin-top: 1.15rem; border-top: 1px solid var(--hair); padding-top: 1rem; }
.detail h4 {
  font-family: var(--display); font-size: 0.6875rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold);
  margin: 1.15rem 0 0.45rem;
}
.detail h4:first-child { margin-top: 0; }
.detail ul, .detail ol { margin: 0; padding-left: 1.2rem; }
.detail li { margin-bottom: 0.35rem; }
.detail li::marker { color: var(--stone-2); }
.detail .lore { color: var(--fg); font-style: italic; margin: 0; }
.detail .caution { color: var(--burn); font-size: 0.9375rem; font-style: italic; }
.detail small { color: var(--muted); }
.ing__nature {
  color: var(--ing-swatch); font-family: var(--display);
  font-size: 0.625rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.var--warmer { color: var(--gold); }
.var--cooler { color: var(--stone-2); }

/* ============================================================
   Footer
   ============================================================ */
.foot {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap;
  padding: 1.5rem clamp(1rem, 4vw, 2rem) calc(2rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--hair);
  color: var(--muted); font-size: 0.8125rem;
}
.foot__brand {
  display: inline-flex; align-items: center; gap: 0.5rem;
  color: var(--muted); text-decoration: none;
  font-family: var(--display); font-size: 0.68rem;
  letter-spacing: 0.14em; text-transform: lowercase;
}
.foot__brand:hover { color: var(--gold); }
.foot__logo { display: block; opacity: 0.85; }
.foot__note { font-style: italic; opacity: 0.8; }
.foot__ver { font-variant-numeric: tabular-nums; opacity: 0.6; margin-left: auto; }
@media (max-width: 34rem) { .foot__note { order: 3; width: 100%; text-align: center; } }

@media (max-width: 30rem) {
  .scale__name { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ============================================================
   Recipes browser — cloned from BTF's cards browser so the two
   apps stay one design. Suit chips become course chips; the
   suit accent becomes the dish's own thermal colour.
   ============================================================ */

body.is-locked { overflow: hidden; }

.tabbar {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 0.7rem);
  right: calc(env(safe-area-inset-right, 0px) + 0.9rem);
  /* Above the recipe view (240) and the browsers (220). The cart badge is the
     confirmation for "Cook it", so it has to be visible from the very screen
     that fires it — and reachable, not just visible. */
  z-index: 300;
  display: flex;
  gap: 0.5rem;
}

.deck-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.6rem;
  color: var(--muted);
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 0.45em 0.9em;
  cursor: pointer;
  opacity: 0.6;
  transition: all 0.3s var(--ease);
}
.deck-tab:hover { opacity: 1; color: var(--gold); border-color: var(--gold); }
.deck-tab__glyph { color: var(--gold); font-size: 1.05em; }

.browser__eyebrow {
  margin: 0 0 0.4rem;
  font-family: var(--display);
  letter-spacing: 0.34em;
  text-transform: uppercase;
  font-size: clamp(0.6rem, 1.4vw, 0.78rem);
  color: var(--gold);
}
.browser__title {
  margin: 0 0 0.4rem;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.8rem, 5vw, 3rem);
  color: var(--fg);
}
.browser__count {
  margin: 0;
  font-family: var(--display);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.62rem;
  color: var(--muted);
}

.cardsbrowser {
  position: fixed;
  inset: 0;
  z-index: 220;
  overflow-y: auto;
  overscroll-behavior: contain;   /* don't let scroll chain to a browser back/refresh */
  /* No bottom padding: a sticky child can only stick within its parent's
     box, so padding here would float the Roll bar above the screen edge.
     .rollbar owns the bottom spacing instead. */
  padding: clamp(1rem, 3vh, 2rem) clamp(1rem, 4vw, 3rem) 0;
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(123,68,189,0.18), transparent 70%),
    linear-gradient(160deg, var(--void), var(--void-2) 70%, var(--void-3));
}
.cardsbrowser[hidden] { display: none; }
.cardsbrowser__inner { max-width: 760px; margin: 0 auto; }
.cardsbrowser__head { text-align: center; margin-bottom: clamp(0.8rem, 2.5vh, 1.4rem); }

.cardsbar {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.3rem 0 0.6rem;
}
.cardsbar__back, .cardsbar__draw {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 0.66rem;
  border-radius: 999px;
  padding: 0.6em 1.1em;
  cursor: pointer;
  transition: all 0.25s var(--ease);
}
.cardsbar__back {
  color: var(--muted);
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--hair);
}
.cardsbar__back:hover { color: var(--fg); border-color: rgba(202,166,239,0.5); }
.cardsbar__draw {
  color: var(--void);
  background: linear-gradient(180deg, var(--gold-hi), var(--gold));
  border: 1px solid var(--gold);
  box-shadow: 0 0 18px -2px rgba(233,200,125,0.6);
}
.cardsbar__draw:hover { filter: brightness(1.06); }

.suitbar {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 0.5rem; margin-bottom: clamp(1rem, 3vh, 1.6rem);
}
.suitchip {
  display: inline-flex; align-items: center; gap: 0.4em;
  font-family: var(--display); font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; font-size: 0.66rem;
  color: var(--muted); background: rgba(255,255,255,0.03);
  border: 1px solid var(--hair); border-radius: 999px;
  padding: 0.5em 0.95em; cursor: pointer; transition: all 0.25s var(--ease);
}
.suitchip:hover { color: var(--fg); border-color: rgba(202,166,239,0.5); }
.suitchip[aria-selected="true"] {
  color: var(--void); background: linear-gradient(180deg, var(--gold-hi), var(--gold));
  border-color: var(--gold);
}
.suitchip__glyph { font-size: 1.1em; }

/* The arrows were flex items eating roughly a quarter of a phone screen
   between them. They are hints, not structure — overlay them. */
.carousel { position: relative; }
.carousel__track {
  display: flex; align-items: flex-start;
  gap: clamp(0.8rem, 3vw, 1.4rem);
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  overscroll-behavior-x: contain;   /* swiping past the ends won't trigger browser back */
  padding: 0.4rem 0.2rem 1rem; scrollbar-width: thin;
}
.carousel__nav {
  position: absolute; top: 38%; z-index: 3;
  width: 2.2rem; height: 2.2rem; border-radius: 50%;
  display: grid; place-items: center; font-size: 1.3rem; line-height: 1;
  color: var(--fg); background: rgba(10,7,18,0.72);
  border: 1px solid var(--hair); cursor: pointer;
  opacity: 0.35; transition: opacity 0.25s var(--ease), border-color 0.25s var(--ease);
}
.carousel:hover .carousel__nav { opacity: 0.9; }
.carousel__nav:hover { opacity: 1; border-color: var(--gold); color: var(--gold); }
.carousel__nav--prev { left: 0.15rem; }
.carousel__nav--next { right: 0.15rem; }

/* ── the face: one component, used on the table and in the browser ── */
.deckslide {
  display: flex; flex-direction: column; gap: 0.6rem;
  background: linear-gradient(180deg, rgba(28,15,51,0.6), rgba(10,7,18,0.6));
  border: 1px solid color-mix(in srgb, var(--swatch, var(--gold)) 28%, var(--hair));
  border-radius: 16px; padding: clamp(0.8rem, 2.5vw, 1.15rem);
}
.carousel__track > .deckslide {
  flex: 0 0 min(69%, 272px); scroll-snap-align: center;  /* 20% smaller */
}

/* arrived at via #recipes/<slug> */
.deckslide--focus {
  border-color: var(--gold);
  box-shadow: 0 0 34px -4px rgba(233,200,125,0.55);
}

.deckslide__art {
  position: relative;
  /* 25% shorter than the card's true 3:5 — the picture is a cue here, and the
     title above it is doing the identifying work. */
  width: 100%; aspect-ratio: 4 / 5;
  border-radius: 12px; overflow: hidden;
  background: rgba(0,0,0,0.3);
}
.deckslide__art img {
  width: 100%; height: 100%; display: block;
  object-fit: cover;
  /* The card carries its own printed title at the foot. A centred crop slices
     that band in half; anchoring near the top drops it cleanly instead, and the
     HTML title above the picture is doing that job here anyway. */
  object-position: 50% 6%;
}
.deckslide__art--bare {
  display: grid; place-items: center;
  background:
    radial-gradient(ellipse 70% 50% at 50% 35%,
      color-mix(in srgb, var(--swatch) 30%, transparent), transparent 70%),
    linear-gradient(180deg, var(--stone-deep), var(--void-2));
}
.deckslide__glyph {
  font-size: clamp(2.5rem, 10vw, 4rem); color: var(--swatch);
  filter: drop-shadow(0 0 20px color-mix(in srgb, var(--swatch) 45%, transparent));
}
.deckslide__hanzi {
  position: absolute; bottom: 0.7rem; right: 0.85rem;
  font-family: var(--display); font-size: 1.4rem;
  color: var(--swatch); opacity: 0.55;
}

/* Sourcing badges. Every dish earns "traditional", so that one is deliberately
   quiet — the eye should catch the market badges, whose absence is the signal. */
.deckslide__badges {
  margin: 0; display: flex; flex-wrap: wrap; gap: 0.3rem;
}
.badge {
  font-family: var(--display); font-size: 0.55rem;
  letter-spacing: 0.16em; text-transform: uppercase;
  padding: 0.25em 0.6em; border-radius: 999px;
  border: 1px solid var(--hair); color: var(--muted);
}
.badge--traditional { opacity: 0.6; }
.badge--us {
  color: var(--gold-hi); border-color: rgba(233,200,125,0.55);
  background: rgba(233,200,125,0.08);
}

.deckslide__eyebrow {
  margin: 0; font-family: var(--display); letter-spacing: 0.28em;
  text-transform: uppercase; font-size: 0.6rem; color: var(--swatch);
}
.deckslide__title {
  margin: 0; font-family: var(--display); font-weight: 800;
  font-size: 1.26rem; line-height: 1.12; color: var(--fg);
}
.deckslide__sum  { margin: 0; font-size: 0.95rem; line-height: 1.45; color: var(--fg); }
.deckslide__meta { margin: 0; font-size: 0.85rem; color: var(--muted); font-style: italic; }


/* ── Materials ──────────────────────────────────────────────────────────── */
.cardsbrowser__inner--narrow { max-width: 30rem; }

.mats__preview {
  display: flex; justify-content: center;
  padding: 0.5rem 0 1rem;
}
.mats__empty {
  text-align: center; color: var(--muted); font-style: italic;
  padding: 2rem 1rem;
}
.mats__note {
  margin: 0.5rem 0 0; text-align: center;
  font-size: 0.8125rem; color: var(--muted); font-style: italic;
}
.cardsbar__draw:disabled { opacity: 0.35; cursor: not-allowed; filter: none; }

.mats__text {
  width: 100%; resize: vertical;
  background: rgba(10,7,18,0.6); color: var(--fg);
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: 0.85rem 1rem;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.8125rem; line-height: 1.55;
}
.mats__text:focus { outline: 1px solid var(--gold); }
.mats__more {
  margin-top: 0.85rem; font-size: 0.8125rem; color: var(--muted);
}
.mats__more summary {
  cursor: pointer; font-family: var(--display);
  letter-spacing: 0.12em; text-transform: uppercase; font-size: 0.65rem;
}

.bootfail {
  margin: 0 0 1.5rem; padding: 0.85rem 1rem;
  border: 1px solid var(--burn); border-radius: var(--r);
  background: rgba(255,90,60,0.08);
  color: var(--fg); font-size: 0.9375rem; text-align: center;
}

/* ── The recipe view (layout A) ──────────────────────────────────────────
   A rail carrying the card, the facts and the action, sticky beside the
   recipe on desktop and pinned to the top on a phone. One grid that
   collapses — not two layouts to keep in step. */
.lightbox {
  position: fixed; inset: 0; z-index: 240;
  overflow-y: auto; overscroll-behavior: contain;
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(123,68,189,0.18), transparent 70%),
    linear-gradient(160deg, var(--void), var(--void-2) 70%, var(--void-3));
  animation: rise 0.25s var(--ease) both;
}
.lightbox[hidden] { display: none; }

.rx {
  display: grid;
  /* minmax(0,...) on BOTH tracks. A bare fr has min-width:auto, so any wide
     child widens the grid rather than being constrained by it — which is what
     pushed the rail's buttons off the right edge on a phone. */
  grid-template-columns: minmax(190px, 1fr) minmax(0, 3fr);
  gap: clamp(1rem, 3vw, 1.9rem);
  max-width: 62rem; margin: 0 auto;
  padding: clamp(1rem, 3vh, 1.6rem) clamp(1rem, 4vw, 2rem) 4rem;
  align-items: start;
}

.rx__rail {
  position: sticky; top: clamp(1rem, 3vh, 1.6rem);
  display: flex; flex-direction: column; gap: 0.7rem;
  min-width: 0;
}
.rx__art {
  width: 100%; height: auto; display: block; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--swatch) 45%, var(--hair));
  box-shadow: 0 14px 44px -22px #000;
}
.rx__art[hidden] { display: none; }

.rx__nat { display: flex; align-items: baseline; gap: 0.5rem; margin: 0; color: var(--swatch); }
.rx__nat b { font-family: var(--display); font-size: 1.5rem; }
.rx__nat span {
  font-family: var(--display); font-size: 0.66rem;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.rx__meta { margin: 0; font-size: 0.8125rem; color: var(--muted); font-style: italic; }
.rx__pool {
  margin: 0; font-family: var(--display); font-size: 0.6rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); opacity: 0.85;
}

/* Actions sit directly under the card. The facts and tags below them are
   reference, not action — on a short screen at high zoom they can scroll away
   without taking the buttons with them. */
.rx__meat { display: none; }
.rx__facts-pop { display: flex; flex-direction: column; gap: 0.55rem; }
.rx__facts-pop[hidden] { display: none; }

.rx__acts { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.15rem; }
.rx__acts button {
  width: 100%; min-height: 48px; cursor: pointer;
  font-family: var(--display); font-size: 0.72rem;
  letter-spacing: 0.14em; text-transform: uppercase; border-radius: 10px;
  transition: filter 0.2s var(--ease), background 0.2s var(--ease);
}
.rx__cook {
  border: 0; color: var(--void);
  background: linear-gradient(180deg, var(--gold-hi), var(--gold));
  box-shadow: 0 0 18px -2px rgba(233,200,125,0.6);
}
.rx__cook:hover { filter: brightness(1.06); }
.rx__cook.is-done {
  background: linear-gradient(180deg, #cfe8c6, #9ecf90);
  box-shadow: 0 0 20px -2px rgba(158,207,144,0.55);
}
.rx__shuffle {
  background: rgba(255,255,255,0.05);
  border: 1px solid color-mix(in srgb, var(--swatch) 45%, var(--hair));
  color: var(--fg);
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
}
.rx__shuffle:hover:not(:disabled) { border-color: var(--swatch); color: var(--swatch); }
.rx__shuffle:disabled { opacity: 0.35; cursor: not-allowed; }
.rx__glyph { font-size: 1.05em; line-height: 1; }

.rx__back {
  background: rgba(255,255,255,0.04); border: 1px solid var(--hair); color: var(--muted);
  min-height: 42px !important;
}
.rx__back:hover { color: var(--fg); border-color: rgba(202,166,239,0.5); }

.rx__eyebrow {
  margin: 0; font-family: var(--display); font-size: 0.62rem;
  letter-spacing: 0.28em; text-transform: uppercase; color: var(--swatch);
}
.rx__title {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.5rem, 4vw, 2rem); line-height: 1.1;
  color: var(--fg); margin: 0.15rem 0 0.4rem;
}
.rx__facts { display: none; }        /* desktop: the rail already says all this */
.rx__railtop { display: contents; }  /* desktop: card and nature stack normally */
.rx__nat--top { display: none; }
.rx__sum { font-size: 1.05rem; margin: 0.2rem 0 1rem; color: var(--fg); }

.rx__body { min-width: 0; }
.rx__body .detail { border: 0; padding: 0; margin: 0; text-align: left; }
.rx__body h4 {
  font-family: var(--display); font-size: 0.66rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold);
  margin: 1.4rem 0 0.5rem;
}
.rx__body ul, .rx__body ol { margin: 0; padding-left: 1.2rem; }
.rx__body li { margin-bottom: 0.35rem; }
.rx__body li::marker { color: var(--stone-2); }

/* Landscape phone: wide enough for the desktop rail, far too short for it.
   A full-height card pushed every action below the fold. Keyed on height,
   because the problem is vertical space, not width. */
@media (max-height: 560px) and (min-width: 44.01rem) {
  /* Landscape phone: the desktop stack, compressed. Card, the three actions,
     temperature, then tags — which are allowed to run off the bottom, since
     they are reference and the actions are not. */
  .rx { padding-top: 0.6rem; grid-template-columns: minmax(150px, 1fr) minmax(0, 3.4fr); }
  .rx__rail { display: flex; flex-direction: column; gap: 0.4rem; }
  .rx__art { width: 100%; height: auto; max-height: 34vh; object-fit: contain; margin: 0; }
  .rx__acts { flex-direction: column; gap: 0.3rem; margin: 0; }
  .rx__acts button { min-height: 34px !important; font-size: 0.62rem; }
  .rx__acts .rx__cook span { display: inline; }
  .rx__acts .rx__word { display: inline; }
  .rx__facts-pop { gap: 0.3rem; }
  .rx__nat b { font-size: 1.15rem; }
  .rx__meta, .rx__pool { font-size: 0.68rem; }
}

@media (max-width: 44rem) {
  .rx { grid-template-columns: minmax(0, 1fr); gap: 0; padding: 0 0 2rem; }

  /* Portrait: a fixed-height header that reads left to right — card, the three
     actions, then the facts collapsed behind a meatball. The right edge is kept
     clear for the Cart tab, which is fixed over this row. */
  .rx__rail {
    position: sticky; top: 0; z-index: 5;
    display: grid;
    grid-template-columns: 62px minmax(0, 1fr) 34px;
    gap: 0.5rem; align-items: stretch;
    padding: 0.5rem 0.6rem 0.5rem 0.7rem;
    padding-right: 5.4rem;                 /* room for the Cart tab */
    background: linear-gradient(180deg, var(--void-2) 55%, rgba(20,11,34,0.97));
    border-bottom: 1px solid var(--hair);
    box-shadow: 0 10px 22px -16px #000;
  }
  .rx__railtop { display: contents; }
  .rx__art {
    grid-column: 1; width: 62px; height: 104px; object-fit: cover; border-radius: 6px;
  }
  .rx__nat--top { display: none; }

  .rx__acts {
    grid-column: 2; margin: 0; gap: 0.28rem;
    display: grid; grid-template-rows: repeat(3, 1fr); min-width: 0;
  }
  .rx__acts button { width: 100%; min-height: 0 !important; font-size: 0.6rem; padding: 0 0.5rem; }
  .rx__acts .rx__word { display: inline; }
  .rx__acts .rx__cook span { display: none; }

  .rx__meat {
    display: block; grid-column: 3; align-self: center;
    width: 34px; height: 34px; border-radius: 50%;
    background: rgba(255,255,255,0.05); border: 1px solid var(--hair);
    color: var(--muted); font-size: 1.1rem; line-height: 1; cursor: pointer;
  }
  .rx__meat[aria-expanded="true"] { color: var(--gold); border-color: var(--gold); }

  .rx__facts-pop {
    position: absolute; top: 100%; right: 0.6rem; z-index: 6;
    min-width: 12rem; padding: 0.7rem 0.85rem;
    background: var(--void-2); border: 1px solid var(--hair);
    border-radius: var(--r); box-shadow: 0 14px 30px -14px #000;
  }

  .rx__facts { display: none; }          /* the meatball carries these now */


  .rx__body { padding: 1rem 0.95rem 0; }
}

/* the cards are now tappable, so say so */
.carousel__track > .deckslide { cursor: pointer; }
.carousel__track > .deckslide:active { transform: scale(0.985); }

/* rolled cards open the same lightbox the browser uses */
.slot .deckslide { cursor: pointer; }
.slot .deckslide:active { transform: scale(0.99); }
/* the lightbox now carries the full recipe, so give it room to scroll */
.lightbox .detail { text-align: left; margin-top: 1rem; }
.lightbox__inner { padding-bottom: 1rem; }

/* ── Cart ───────────────────────────────────────────────────────────────── */
.deck-tab__count {
  display: inline-grid; place-items: center;
  min-width: 1.35em; height: 1.35em; padding: 0 0.3em;
  border-radius: 999px;
  background: var(--gold); color: var(--void);
  font-size: 0.85em; font-weight: 700; letter-spacing: 0;
}
.deck-tab__count[hidden] { display: none; }

/* Inside a recipe or a panel, "Recipes" is redundant — Back already goes where
   it would — so Home takes its slot instead. Getting out used to mean walking
   back one frame at a time; from anywhere it is now one tap. The strip stays
   two tabs wide either way, and Cart never moves, since it is the confirmation
   target for Cook it. */
#home-tab { display: none; }
body.is-locked #home-tab { display: inline-flex; }
body.is-locked #recipes-tab { display: none; }

/* In a recipe the top-right is spoken for: Cart sits there and the sticky rail
   reserves width for one tab, so a second one landed on Cook it. Home drops to
   the far corner instead — out of the way of every action, and closer to a
   thumb than the place it came from. */
body.is-recipe #home-tab {
  position: fixed;
  top: auto; right: auto;
  left: calc(env(safe-area-inset-left, 0px) + 0.9rem);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 0.9rem);
  z-index: 300;
  opacity: 0.92;
  background: rgba(10,7,18,0.82);
  backdrop-filter: blur(6px);
  box-shadow: 0 8px 20px -10px #000;
}

/* ── About: contents, and the terms below the rule ───────────────────────── */
.aboutnav { margin: 0 0 1.4rem; }
.aboutnav__head {
  margin: 0 0 0.35rem;
  font-family: var(--display); font-size: 0.62rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold);
}
.aboutnav__list { margin: 0; padding-left: 1.2rem; color: var(--muted); }
.aboutnav__list li { margin-bottom: 0.15rem; }
.aboutnav__link {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--stone-2); text-decoration: underline;
  text-underline-offset: 3px; text-decoration-color: rgba(178,126,232,0.4);
}
.aboutnav__link:hover { color: var(--gold); }

/* Deliberately heavy. The terms are a different KIND of text from the essay
   above them, and a hairline would read as one more paragraph break. */
.aboutrule {
  border: 0; height: 2px; margin: 2.5rem 0 1.8rem;
  background: linear-gradient(90deg, transparent, var(--gold) 20%, var(--gold) 80%, transparent);
  opacity: 0.55;
}
.aboutterms__title {
  font-family: var(--display); font-size: 1.15rem;
  letter-spacing: 0.06em; color: var(--gold-hi); margin: 0 0 0.9rem;
}
/* Legal text set to be READ: the all-caps is the source's, so give it room
   rather than compounding it with tight leading. */
.legal {
  font-size: 0.78rem; line-height: 1.75; letter-spacing: 0.02em;
  color: var(--muted);
}

.cartlist { list-style: none; margin: 0 0 1.25rem; padding: 0; display: grid; gap: 0.4rem; }
.cartrow {
  display: grid; grid-template-columns: 1fr auto; align-items: stretch;
  column-gap: 0.4rem;
  background: rgba(42,22,64,0.45);
  border: 1px solid var(--hair); border-left: 3px solid var(--swatch);
  border-radius: var(--r);
  overflow: hidden;
}
/* the row is the way back to the recipe, so make the whole thing the target */
.cartrow__open {
  display: flex; flex-direction: column; gap: 0.1rem;
  text-align: left; background: none; border: 0; cursor: pointer;
  padding: 0.65rem 0.5rem 0.65rem 0.75rem; min-height: 48px;
  font: inherit; color: inherit;
}
.cartrow__open:hover .cartrow__name,
.cartrow__open:focus-visible .cartrow__name { color: var(--gold); }
.cartrow__open:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.cartrow__name { font-family: var(--display); font-size: 1rem; color: var(--gold-hi); }
.cartrow__meta { font-size: 0.8125rem; color: var(--muted); font-style: italic; }
.cartrow__cue {
  font-family: var(--display); font-style: normal; font-size: 0.6rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--swatch);
}
.cartrow__rm {
  width: 2.75rem; min-height: 48px; border: 0; border-left: 1px solid var(--hair);
  background: none; color: var(--muted);
  font-size: 1.1rem; line-height: 1; cursor: pointer;
}
.cartrow__rm:hover { color: var(--burn); border-color: var(--burn); }

.shop__head {
  font-family: var(--display); font-size: 0.65rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold);
  margin: 0 0 0.5rem;
}
.shop { margin: 0 0 1rem; padding-left: 1.15rem; }
.shop li { margin-bottom: 0.3rem; }
.shop li::marker { color: var(--stone-2); }
.shop__for {
  font-family: var(--display); font-size: 0.6rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
}

.cart__foot { display: flex; justify-content: center; margin-top: 0.5rem; }


/* the cart answers the press, even when the dish was already saved */
@keyframes cartpop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.35); }
  100% { transform: scale(1); }
}
.deck-tab.is-confirming {
  color: var(--gold); border-color: var(--gold); opacity: 1;
  box-shadow: 0 0 22px -4px rgba(233,200,125,0.8);
}
.deck-tab.is-confirming .deck-tab__count {
  animation: cartpop 0.55s var(--ease);
  background: #9ecf90; color: var(--void);
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Search, roll note, About link ───────────────────────────────────────── */
.findrow { margin: 0 0 0.8rem; }
.find {
  width: 100%; padding: 0.85rem 1rem;
  background: rgba(10,7,18,0.55); color: var(--fg);
  border: 1px solid var(--hair); border-radius: var(--r);
  font-family: var(--body); font-size: 1rem;
}
.find::placeholder { color: var(--muted); font-style: italic; }
.find:focus { outline: none; border-color: var(--gold); }
.findrow--inpanel { margin: 0 0 0.9rem; }

.roll-note {
  margin: 0.5rem 0 0; text-align: center;
  font-size: 0.8125rem; color: var(--muted); font-style: italic;
}
.aboutlink { margin: 1.6rem 0 0; text-align: center; }
.aboutlink button {
  background: none; border: 0; cursor: pointer;
  font-family: var(--display); font-size: 0.68rem;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--hair); padding: 0.2em 0;
}
.aboutlink button:hover { color: var(--gold); border-color: var(--gold); }

/* ── The big Roll at the top of a dealt deck ─────────────────────────────── */
.bigroll {
  width: 100%; display: block; cursor: pointer;
  padding: 0.85rem 1rem 0.75rem;
  margin: 0;
  border: 0; border-radius: var(--r);
  background: linear-gradient(100deg, var(--gold), var(--gold-hi) 55%, var(--gold));
  box-shadow: 0 0 28px -6px rgba(233,200,125,0.55);
  transition: filter 0.2s var(--ease), transform 0.12s var(--ease);
}
.bigroll:hover { filter: brightness(1.06); }
.bigroll:active { transform: translateY(1px); }
.bigroll__word {
  display: block; font-family: var(--display); font-weight: 800;
  font-size: 1.5rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--void);
}
.bigroll__sub {
  display: block; margin-top: 0.1rem;
  font-family: var(--body); font-style: italic; font-size: 0.8rem;
  color: rgba(10,7,18,0.72);
}

/* ── Filter pills: the escape hatch from a narrow pool ───────────────────── */
.filterbar { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; margin: 0 0 0.8rem; }
.filterbar:empty { display: none; }
.pill {
  display: inline-flex; align-items: center; gap: 0.45em;
  padding: 0.35em 0.8em; border-radius: 999px; cursor: pointer;
  background: color-mix(in srgb, var(--stone) 26%, transparent);
  border: 1px solid rgba(202,166,239,0.4); color: var(--fg);
  font-family: var(--display); font-size: 0.66rem;
  letter-spacing: 0.1em; text-transform: uppercase;
}
.pill:hover { border-color: var(--burn); color: var(--burn); }
.pill__hint { font-size: 0.72rem; color: var(--muted); font-style: italic; }

/* ── About ───────────────────────────────────────────────────────────────── */
.aboutbody { font-size: 1rem; line-height: 1.6; }
.aboutbody h4 {
  font-family: var(--display); font-size: 0.66rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold);
  margin: 1.5rem 0 0.4rem;
}
.aboutbody h4:first-child { margin-top: 0; }
.aboutbody p { margin: 0 0 0.6rem; color: var(--fg); }

/* the brand belongs on every view, including a recipe */
.foot--inpanel {
  margin-top: 2rem; padding-left: 0; padding-right: 0;
  border-top: 1px solid var(--hair);
}

/* ── the table ──────────────────────────────────────────────────────────────
   Where a roll lands. The wood is a real tiling texture rather than a gradient
   because a gradient at this size reads as a brown box, not a surface; the
   overlays give it the light falloff a flat tile can't have on its own.
   One column per slot, so Dinner's three cards sit side by side and the tier
   is visible in the layout instead of stated in a caption. */
.table {
  border-radius: var(--r);
  padding: clamp(0.9rem, 3vw, 1.6rem);
  background-image:
    radial-gradient(ellipse 90% 70% at 50% 0%, rgba(255,243,207,0.14), transparent 65%),
    linear-gradient(180deg, rgba(10,7,18,0.18), rgba(10,7,18,0.42)),
    url("../img/wood.png");
  background-size: auto, auto, 260px 260px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5), 0 14px 34px -18px rgba(0,0,0,0.9);
}
.table[hidden] { display: none; }

.table__felt {
  display: grid;
  grid-template-columns: repeat(var(--slots, 1), minmax(0, 1fr));
  gap: clamp(0.7rem, 2.5vw, 1.3rem);
  justify-content: center;
}
.table__hint {
  margin: 0.9rem 0 0; text-align: center;
  font-size: 0.78rem; letter-spacing: 0.04em; color: rgba(236,230,247,0.62);
  text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}

.tablecard { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }

.tablecard__face {
  display: block; width: 100%; padding: 0; cursor: pointer;
  background: none; border: 0; border-radius: 6px;
  /* The card sits ON the wood, so it needs a cast shadow, not a border. */
  box-shadow: 0 10px 20px -8px rgba(0,0,0,0.85), 0 2px 4px rgba(0,0,0,0.5);
  transition: transform 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.tablecard__face:hover,
.tablecard__face:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 18px 30px -10px rgba(0,0,0,0.9), 0 0 0 1px rgba(233,200,125,0.5);
  outline: none;
}
.tablecard__img { display: block; width: 100%; height: auto; border-radius: 6px; }

/* No art yet: still a 2:3 card, so a mixed table doesn't go ragged. */
.tablecard__bare {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.6rem; aspect-ratio: 2 / 3; border-radius: 6px; padding: 1rem;
  background: linear-gradient(180deg, color-mix(in srgb, var(--swatch) 26%, var(--void-2)), var(--void));
  border: 1px solid var(--hair);
}
.tablecard__glyph { font-size: 2rem; color: var(--swatch); }
.tablecard__name {
  font-family: var(--display); font-size: 0.82rem; line-height: 1.3;
  text-align: center; color: var(--fg);
}

.tablecard--empty .tablecard__face--empty {
  display: grid; place-items: center; aspect-ratio: 2 / 3;
  color: rgba(236,230,247,0.35); font-size: 1.6rem;
  border: 1px dashed rgba(236,230,247,0.22); border-radius: 6px;
  background: rgba(10,7,18,0.35); box-shadow: none;
}

.tablecard__keep {
  width: 100%; cursor: pointer;
  padding: 0.5rem 0.6rem; border-radius: 6px;
  font-family: var(--display); font-size: 0.74rem;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--void); background: var(--gold); border: 1px solid transparent;
  transition: opacity 0.2s var(--ease), filter 0.2s var(--ease);
}
.tablecard__keep:hover { filter: brightness(1.08); }
.tablecard__keep:disabled {
  cursor: default; background: transparent; color: var(--gold);
  border-color: rgba(233,200,125,0.45);
}

/* .suitbar sets display:flex, and an author rule beats the UA sheet's
   [hidden] { display: none } — so hiding it from JS needs saying here. */
.suitbar[hidden] { display: none; }

/* Hover-reveal is a pointer affordance only. On touch there is no hover, so
   the button must be there from the start or Keep is undiscoverable. Even with
   a pointer it only recedes: a button at zero opacity is a button nobody knows
   to look for. */
@media (hover: hover) and (pointer: fine) {
  .tablecard__keep { opacity: 0.34; }
  .tablecard:hover .tablecard__keep,
  .tablecard:focus-within .tablecard__keep,
  .tablecard.is-kept .tablecard__keep { opacity: 1; }
}

/* Kept: settled, and visibly out of the next deal. */
.tablecard.is-kept .tablecard__face {
  box-shadow: 0 10px 20px -8px rgba(0,0,0,0.85), 0 0 0 2px var(--gold);
}

/* On the table, search is a detour: you came here to be dealt something, not
   to look one up. It folds behind a meatball so the cards start higher — and it
   is reachable in landscape again, where the row itself cost too much height
   to keep on screen. The browser view keeps its search inline, since there
   looking things up IS the task. */
.cardsbar__meat {
  display: none;
  width: 30px; height: 30px; flex: none;
  border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,0.05); border: 1px solid var(--hair);
  color: var(--muted); font-size: 1.15rem; line-height: 1;
}
.cardsbar__meat[aria-expanded="true"] { color: var(--gold); border-color: var(--gold); }
.is-table .cardsbar__meat { display: inline-grid; place-items: center; }
/* Sits beside Back, at the far left. The right end of this row is under the
   fixed Cart tab, which is no place for a control. */
.cardsbar__meat { margin-right: auto; }

.cart__tools { display: flex; justify-content: flex-end; margin-bottom: 0.9rem; }

/* The cart opens OVER the deck, so Back from it lands you on your table again.
   Both are .cardsbrowser at the same z-index and #cartbrowser comes first in
   the document, so without this the later panel simply painted on top of it —
   the cart opened, invisibly, behind the table. */
#cartbrowser { z-index: 230; }
.is-table .findrow--inpanel { display: none; }
.is-table.filters-open .findrow--inpanel { display: block; }

/* The Roll floor. Sticky rather than merely last, because a Dinner table can
   be taller than the screen and the whole point of moving it down was that a
   thumb can always reach it. */
.rollbar {
  position: sticky;
  bottom: 0;
  z-index: 4;
  margin-top: clamp(0.8rem, 2.5vh, 1.3rem);
  padding: 0.6rem 0 calc(env(safe-area-inset-bottom, 0px) + 0.6rem);
  /* Fades the table out underneath instead of cutting it with a hard edge. */
  background: linear-gradient(180deg, transparent, var(--void-2) 45%, var(--void-2));
}

/* On screen the card art's own title is print-sized and unreadable on a phone,
   so the name is set again here in the display face. min-height holds two
   lines so a one-line and a two-line title keep their cards aligned in a row. */
.tablecard__title {
  margin: 0 0 0.15rem;
  /* A FIXED two-line box, not a minimum. Left to size itself, a one-line and a
     three-line title start their cards at different heights and a Dinner row
     goes ragged. Two lines holds nearly every title; the few that overrun are
     clamped, and the full name is on the card art and in the recipe anyway. */
  height: 2.4em; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  font-family: var(--display); font-weight: 600;
  font-size: 0.9rem; line-height: 1.2; text-align: center;
  color: var(--gold-hi);
  text-shadow: 0 1px 4px rgba(0,0,0,0.9), 0 0 14px rgba(10,7,18,0.7);
}

/* A single card shouldn't inflate to the full 760px container — a tarot card
   is a hand-sized object and reads wrong at poster scale. */
.table__felt { max-width: calc(var(--slots, 1) * 15rem); margin: 0 auto; }

/* Phones: three 2:3 cards across 360px leaves ~100px each, which is a thumbnail
   rather than a card. Let them wrap instead. */
@media (max-width: 30rem) {
  .table__felt { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }
}

/* Landscape phone. ~390px of height, and the panel chrome alone was taller
   than that: press Roll and the cards you just dealt sit entirely below the
   fold, which reads as the button doing nothing. Keyed on height, because the
   problem is vertical space — the same width in portrait is fine.
   Cards are sized down too, since a card whose width comes from a third of an
   844px viewport is 390px tall and could never fit beside the chrome. */
@media (max-height: 35rem) {
  .cardsbrowser { padding-top: 0.4rem; padding-bottom: 1rem; }
  /* The Cart tab is fixed over this row, and with the bar pulled to the top it
     lands straight on the count. Reserve its width. */
  .cardsbar { padding: 0.15rem 6.5rem 0.35rem 0; }
  .bigroll { padding: 0.4rem 1rem 0.35rem; margin-bottom: 0.5rem; }
  .bigroll__word { font-size: 1.05rem; letter-spacing: 0.16em; }
  .bigroll__sub { display: none; }
  .filterbar { margin-bottom: 0.4rem; }
  /* Search costs ~45px of a 390px screen and the pills already widen the pool.
     It is one tap away in portrait, and the sticky Roll bar needs the room. */
  .findrow--inpanel { display: none; }
  .table { padding: 0.4rem; }
  /* Small enough that the card AND its Keep button clear the fold — seeing
     the whole hand beats seeing three big cropped ones. Tap to enlarge. */
  .table__felt { max-width: calc(var(--slots, 1) * 6.5rem); gap: 0.45rem; }
  .table__hint { display: none; }
  /* Keep rides ON the card's bottom edge here rather than under it. Out of
     flow it costs no height, which is the whole budget in landscape — and the
     card's own printed title is illegible at 100px wide anyway, so covering
     that band loses nothing the title row above has not already said. */
  .tablecard { position: relative; }
  .tablecard__keep {
    position: absolute; left: 0; right: 0; bottom: 0;
    padding: 0.28rem 0.4rem; font-size: 0.62rem;
    border-radius: 0 0 6px 6px;
    background: rgba(233,200,125,0.94);
  }
  .tablecard.is-kept .tablecard__keep { background: rgba(10,7,18,0.86); }
  .tablecard__title { font-size: 0.7rem; margin-bottom: 0.1rem; }
  .rollbar { margin-top: 0.5rem; padding: 0.4rem 0 0.4rem; }
  .bigroll { padding: 0.35rem 1rem 0.3rem; }
}
