/* There is almost nothing here on purpose. The page is one canvas edge to edge, and the
   only two pieces of furniture are a hint that leaves as soon as you have understood it,
   and a way back to the rest of the site. */

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100%;
  overflow: hidden;
  background: #04283c;
  color: #dff1fa;
  font: 400 15px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

#tank {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;   /* a drag has to release fish, not scroll the page */
  cursor: crosshair;
}

#hint {
  position: fixed;
  left: 50%;
  bottom: max(7vh, 2.6rem);
  transform: translateX(-50%);
  padding: 0.55rem 1.1rem;
  border-radius: 2rem;
  background: rgba(4, 28, 44, 0.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: rgba(233, 248, 255, 0.86);
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  pointer-events: none;
  animation: fade-in 1.6s 1.2s both;
}

#hint.gone {
  animation: fade-out 0.7s both;
}

@keyframes fade-in  { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; visibility: hidden; } }

#home {
  position: fixed;
  left: max(1.2rem, env(safe-area-inset-left));
  bottom: max(1.1rem, env(safe-area-inset-bottom));
  color: rgba(223, 241, 250, 0.42);
  text-decoration: none;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  transition: color 0.25s;
}
#home:hover, #home:focus-visible { color: rgba(223, 241, 250, 0.95); }

/* The only control on the page, and it only appears once there is something to switch
   off. Sound that cannot be silenced is worse than no sound. */
#speaker {
  position: fixed;
  right: max(1.2rem, env(safe-area-inset-right));
  bottom: max(1.1rem, env(safe-area-inset-bottom));
  appearance: none;
  border: 0;
  background: none;
  padding: 0.2rem 0.1rem;
  color: rgba(223, 241, 250, 0.42);
  font: inherit;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: color 0.25s;
}
#speaker:hover, #speaker:focus-visible { color: rgba(223, 241, 250, 0.95); }
#speaker[hidden] { display: none; }

/* How hungry the tank is, not how much food you are allowed.
   It fills as the fish get hungry and empties as they eat, so it is a reading of the
   water rather than a wallet, and it takes itself off the screen once there is nothing
   worth feeding. It carries its own word, because a bare line at the bottom of a screen
   tells nobody anything. */
.appetite {
  position: fixed;
  left: 50%;
  bottom: max(1.45rem, calc(env(safe-area-inset-bottom) + 1.1rem));
  transform: translateX(-50%);
  width: min(200px, 40vw);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.42rem;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.7s ease;
}
.appetite-track {
  width: 100%;
  height: 2px;
  background: rgba(163, 214, 236, 0.13);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 16%, #000 84%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 16%, #000 84%, transparent);
}
.appetite-track i {
  display: block;
  height: 100%;
  width: 100%;
  transform-origin: left center;
  transform: scaleX(0);
  background: linear-gradient(to right, rgba(198, 240, 255, 0.32), rgba(214, 246, 255, 0.58));
}
.appetite-label {
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(210, 238, 250, 0.4);
}

/* ---------------------------------------------------------------------------------
   THE SHOP

   Three voices, and the contrast between them is the whole design.

   Numbers are Silkscreen, the pixel face the rest of byfuente.com is set in, at exactly
   sixteen pixels with smoothing switched off so it stays crisp. It is the face of a price
   sticker, which is what a price is, and it is the only thing in the tank that belongs to
   the site rather than to the water.

   Names are a serif. Not a decision about elegance: a shop like this is a catalogue of
   specimens, and a specimen has a name set in a book face beside a number set in a ticket
   face. That pairing is a century old and it still works.

   Everything else, the tabs and the small print, is the same quiet sans the rest of the
   tank uses, small and widely spaced, and it never competes with either of the others.
--------------------------------------------------------------------------------- */

@font-face {
  font-family: "Silkscreen";
  src: url("/assets/fonts/silkscreen-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink:    #e9f7fe;
  --ink-2:  rgba(193, 226, 242, 0.74);
  --ink-3:  rgba(157, 200, 222, 0.5);
  --rule:   rgba(150, 205, 230, 0.11);
  --rule-2: rgba(150, 205, 230, 0.06);
  --frag:   #8fe0aa;                /* what the reef pays in */
  --fry:    #ffc46a;                /* the colour of a pellet, and of the fish it buys */
  --serif:  ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --pixel:  "Silkscreen", ui-monospace, monospace;
}

/* ---- one line answering something you just did, gone four seconds later ---- */

#notice {
  position: fixed;
  left: 50%;
  bottom: max(12vh, 5.6rem);
  transform: translateX(-50%);
  padding: 0.5rem 1.05rem;
  border-radius: 2rem;
  background: rgba(4, 26, 40, 0.42);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  color: rgba(233, 248, 255, 0.92);
  font-size: 0.86rem;
  letter-spacing: 0.015em;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.5s ease, transform 0.5s ease;
}
#notice.gone { opacity: 0; transform: translate(-50%, 4px); }
/* with the sheet open, the middle of the screen is not the middle of the tank */
body.shopping #notice { transform: translateX(calc(-50% - min(200px, 50vw))); }
body.shopping #notice.gone { transform: translate(calc(-50% - min(200px, 50vw)), 4px); }

/* ---- the tag ----------------------------------------------------------------------
   A cardboard label of the kind an aquarium shop clips to the glass, hanging in the
   corner on a bit of line and turning slightly in the water. It is the one piece of
   furniture allowed to stay up, and it is allowed because it is a thing in the aquarium
   rather than a control on top of one. No badge, no dot, no number: when the reef becomes
   able to keep something new it warms up once, slowly, and never mentions it again. */

#shoptag {
  position: fixed;
  right: max(1.1rem, env(safe-area-inset-right));
  bottom: max(3.4rem, calc(env(safe-area-inset-bottom) + 3.3rem));
  width: 42px;
  height: 62px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transform-origin: 50% 4%;
  animation: tag-sway 9s ease-in-out infinite;
  filter: drop-shadow(0 3px 10px rgba(1, 14, 24, 0.45));
  transition: filter 0.35s ease;
}
#shoptag svg { width: 100%; height: 100%; display: block; overflow: visible; }
#shoptag .card  { fill: rgba(226, 240, 248, 0.13); stroke: rgba(214, 238, 250, 0.55); stroke-width: 1.4; }
#shoptag .line  { stroke: rgba(214, 238, 250, 0.4); stroke-width: 1.3; stroke-linecap: round; fill: none; }
#shoptag .hole  { fill: none; stroke: rgba(214, 238, 250, 0.45); stroke-width: 1.2; }
#shoptag .rule  { stroke: rgba(214, 238, 250, 0.3); stroke-width: 1.5; stroke-linecap: round; }
#shoptag .fish  { fill: rgba(214, 238, 250, 0.42); }
#shoptag:hover, #shoptag:focus-visible { filter: drop-shadow(0 3px 14px rgba(1, 14, 24, 0.6)); }
#shoptag:hover .card, #shoptag:focus-visible .card {
  fill: rgba(226, 240, 248, 0.2);
  stroke: rgba(230, 246, 255, 0.9);
}
#shoptag:hover .rule { stroke: rgba(230, 246, 255, 0.55); }
#shoptag:hover .fish { fill: rgba(230, 246, 255, 0.7); }
#shoptag:focus-visible { outline: none; }

#shoptag.lit .card { fill: rgba(255, 196, 106, 0.22); stroke: rgba(255, 210, 145, 0.95); }
#shoptag.lit .rule, #shoptag.lit .hole { stroke: rgba(255, 210, 145, 0.75); }
#shoptag.lit .fish { fill: rgba(255, 214, 155, 0.85); }
#shoptag.lit { filter: drop-shadow(0 0 16px rgba(255, 196, 106, 0.45)); }

/* while the sheet is open the tag has nothing to do: the way out is the word close */
body.shopping #shoptag { opacity: 0; pointer-events: none; transition: opacity 0.2s; }

@keyframes tag-sway {
  0%, 100% { transform: rotate(-2.6deg); }
  50%      { transform: rotate(2.2deg); }
}

/* ---- the sheet --------------------------------------------------------------------
   Half the screen at most, and the tank keeps running beside it, undimmed and unpaused,
   because the tank does not stop for anybody. The left edge is a lit hairline rather than
   a border: brightest at the top, which is where the light in this scene comes from. */

.shop {
  position: fixed;
  top: 0;
  right: 0;
  height: 100%;
  width: min(400px, 100vw);
  display: flex;
  flex-direction: column;
  color: var(--ink);
  background: linear-gradient(180deg, rgba(6, 34, 52, 0.9) 0%, rgba(3, 21, 33, 0.94) 100%);
  backdrop-filter: blur(18px) saturate(1.1);
  -webkit-backdrop-filter: blur(18px) saturate(1.1);
  animation: shop-in 0.34s cubic-bezier(0.2, 0.9, 0.25, 1) both;
  overscroll-behavior: contain;
}
.shop[hidden] { display: none; }

.shop::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: linear-gradient(180deg,
    rgba(190, 232, 255, 0.5) 0%,
    rgba(150, 205, 230, 0.16) 38%,
    rgba(150, 205, 230, 0.04) 100%);
}

@keyframes shop-in {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}

/* ---- the purse ---- */

.shop header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: max(1.35rem, env(safe-area-inset-top)) 1.35rem 0.95rem;
}
.purse { display: flex; gap: 1.15rem; }

.coin {
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  font-family: var(--pixel);
  font-size: 16px;
  line-height: 1;
  -webkit-font-smoothing: none;
  font-smooth: never;
  color: var(--ink);
}
.coin::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}
.coin.frags::before { background: var(--frag); box-shadow: 0 0 8px rgba(143, 224, 170, 0.55); }
.coin.fry::before   { background: var(--fry);  box-shadow: 0 0 8px rgba(255, 196, 106, 0.55); }
/* the number is the ticket, the unit is a caption under it: same line, different voice,
   so the figure is what the eye lands on */
.coin i {
  font-style: normal;
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  -webkit-font-smoothing: antialiased;
}
.shop-buy .coin i { color: var(--ink-2); }

.shop-close {
  appearance: none;
  border: 0;
  background: none;
  padding: 0.3rem 0;
  color: var(--ink-3);
  font: inherit;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.22s;
}
.shop-close:hover, .shop-close:focus-visible { color: var(--ink); }

/* ---- the tabs ---- */

.shop nav {
  display: flex;
  /* eight tabs no longer fit on one line at every width, and a row of tabs that scrolls
     sideways hides the last one from anybody who does not know it is there. So it wraps,
     and the underline that marks the open tab keeps working either way. */
  flex-wrap: wrap;
  gap: 0 1.1rem;
  padding: 0 1.35rem;
  border-bottom: 1px solid var(--rule);
}
.shop nav button {
  appearance: none;
  border: 0;
  background: none;
  padding: 0 0 0.75rem;
  margin-top: 0.1rem;
  color: var(--ink-3);
  font: inherit;
  font-size: 0.72rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  cursor: pointer;
  position: relative;
  transition: color 0.22s;
}
.shop nav button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.28s cubic-bezier(0.2, 0.9, 0.25, 1);
}
.shop nav button:hover { color: var(--ink-2); }
.shop nav button.on { color: var(--ink); }
.shop nav button.on::after { transform: scaleX(1); }

/* ---- the list ---- */

.shop-list {
  flex: 1;
  overflow-y: auto;
  padding: 0.4rem 1.35rem 1rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(150, 205, 230, 0.22) transparent;
}
.shop-list::-webkit-scrollbar { width: 6px; }
.shop-list::-webkit-scrollbar-thumb { background: rgba(150, 205, 230, 0.2); border-radius: 3px; }

.shop-head {
  padding: 0.7rem 0 0.9rem;
  font-size: 0.75rem;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--ink-3);
  border-bottom: 1px solid var(--rule-2);
  margin-bottom: 0.2rem;
}

/* ---- the purse ----
   Not a bank balance sitting in a corner all day. It comes up when a shoot is picked or a
   young goes to the shop, says the two numbers, and takes itself away again. That is the
   difference between a purse and a score, and it is also where a new visitor finds out
   where the money comes from, because they watch it arrive as they cause it. */
#purse {
  position: fixed;
  right: max(1.1rem, env(safe-area-inset-right));
  bottom: max(7.2rem, calc(env(safe-area-inset-bottom) + 7.1rem));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
  pointer-events: none;
  transition: opacity 0.55s ease, transform 0.55s ease;
}
#purse.gone { opacity: 0; transform: translateY(5px); }
#purse .coin {
  padding: 0.28rem 0.5rem;
  border-radius: 2px;
  background: rgba(4, 26, 40, 0.5);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
body.shopping #purse { opacity: 0; }

.shop-row {
  display: grid;
  grid-template-columns: 30px 1fr auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--rule-2);
  animation: row-in 0.34s cubic-bezier(0.2, 0.9, 0.25, 1) both;
}
.shop-row:last-child { border-bottom: 0; }
.shop-row:hover .shop-glyph { opacity: 1; }
.shop-row:hover .shop-sub { color: var(--ink-2); }
.shop-row.locked:hover .shop-glyph { opacity: 0.45; }
.shop-glyph, .shop-sub { transition: opacity 0.22s, color 0.22s; }

/* the rows arrive in order rather than all at once, which is the difference between a
   drawer opening and a table appearing */
@keyframes row-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.shop-glyph {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  opacity: 0.75;
}
.shop-glyph svg { width: 100%; height: 100%; display: block; }
.shop-glyph path, .shop-glyph circle, .shop-glyph ellipse, .shop-glyph line {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.shop-glyph .solid { fill: currentColor; stroke: none; }

/* the water rows show the water, which is the only honest way to sell it */
.swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}

.shop-name {
  font-family: var(--serif);
  font-size: 1.02rem;
  line-height: 1.25;
  color: var(--ink);
  letter-spacing: 0.005em;
}
.shop-sub {
  margin-top: 0.2rem;
  font-size: 0.755rem;
  line-height: 1.45;
  letter-spacing: 0.005em;
  color: var(--ink-3);
}

/* the price, as a ticket */
.shop-buy {
  appearance: none;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid rgba(150, 205, 230, 0.2);
  border-radius: 2px;
  background: rgba(150, 205, 230, 0.05);
  padding: 0.42rem 0.6rem 0.4rem;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.2s, border-color 0.2s, transform 0.12s;
}
.shop-buy .coin { color: inherit; }
.shop-buy:hover:not(:disabled) {
  background: rgba(150, 205, 230, 0.14);
  border-color: rgba(190, 232, 255, 0.55);
}
.shop-buy:active:not(:disabled) { transform: translateY(1px); }
.shop-buy:focus-visible { outline: 1px solid rgba(190, 232, 255, 0.8); outline-offset: 2px; }

/* cannot afford it: the price stays legible and the frame goes quiet */
.shop-buy.poor { opacity: 0.5; cursor: default; border-color: var(--rule-2); background: none; }

/* nothing to buy here: no frame at all, just a word */
.shop-buy.flat {
  border-color: transparent;
  background: none;
  cursor: default;
  color: var(--ink-3);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-right: 0;
}

.shop-row.locked .shop-glyph { opacity: 0.3; }
.shop-row.locked .shop-name { color: var(--ink-2); }

/* ---- the line at the bottom ---- */

.shop-note {
  padding: 0.9rem 1.35rem max(1.2rem, calc(env(safe-area-inset-bottom) + 0.9rem));
  border-top: 1px solid var(--rule);
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-3);
  opacity: 0;
  transition: opacity 0.3s;
}
.shop-note.shown { opacity: 1; }

.shop-empty {
  padding: 2.6rem 0 0;
  font-family: var(--serif);
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-3);
  max-width: 22rem;
}

/* ---- the job -----------------------------------------------------------------------
   What to do, on the screen rather than behind a tab, because somebody who cannot see a
   goal will not go looking for one. It brightens when it moves and settles back to almost
   nothing when it has not moved for a few seconds, which is how a thing can be permanent
   without being furniture in front of the view. */

#job {
  position: fixed;
  left: max(1.2rem, env(safe-area-inset-left));
  top: max(1.2rem, env(safe-area-inset-top));
  width: min(232px, 46vw);
  pointer-events: none;
  transition: opacity 0.8s ease;
}
#job.gone { opacity: 0; }
#job.dim { opacity: 0.62; }

.job-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.7rem;
  margin-bottom: 0.45rem;
}
.job-name {
  font-size: 0.73rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(224, 244, 254, 0.95);
  text-shadow: 0 1px 6px rgba(2, 18, 30, 0.55);
}
.coin.job-count {
  font-family: var(--pixel);
  font-size: 16px;
  line-height: 1;
  -webkit-font-smoothing: none;
  font-smooth: never;
  color: rgba(224, 244, 254, 0.95);
  gap: 0;
  text-shadow: 0 1px 6px rgba(2, 18, 30, 0.55);
}
.coin.job-count::before { display: none; }

.job-track {
  height: 2px;
  background: rgba(163, 214, 236, 0.14);
  overflow: hidden;
}
.job-track i {
  display: block;
  height: 100%;
  width: 100%;
  transform-origin: left center;
  transform: scaleX(0);
  background: linear-gradient(to right, rgba(143, 224, 170, 0.5), rgba(143, 224, 170, 0.95));
  transition: transform 0.45s cubic-bezier(0.2, 0.9, 0.25, 1);
}
.job-track.wide { margin-top: 0.5rem; max-width: 11rem; }

/* the board, inside the sheet */
.job-row { align-items: start; }
.job-row .shop-glyph { margin-top: 0.15rem; }
.job-mark svg circle { stroke-width: 1.3; }
.job-row:not(.first) .job-mark { opacity: 0.45; }
.job-pay {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.45rem;
}
.job-pay .coin.job-count { color: var(--ink-2); }

/* ---- the card ---------------------------------------------------------------------
   Who that fish is, or what that rock is. It follows the thing it describes across the
   screen and closes itself the moment that thing is gone. Same three voices as the sheet:
   a serif name, pixel numbers, quiet sans labels. */

.card {
  position: fixed;
  width: 232px;
  padding: 0.95rem 1.05rem 1rem;
  background: linear-gradient(180deg, rgba(6, 34, 52, 0.82) 0%, rgba(3, 21, 33, 0.88) 100%);
  backdrop-filter: blur(12px) saturate(1.1);
  -webkit-backdrop-filter: blur(12px) saturate(1.1);
  border-top: 1px solid rgba(190, 232, 255, 0.28);
  color: var(--ink);
  pointer-events: none;
  animation: card-in 0.26s cubic-bezier(0.2, 0.9, 0.25, 1) both;
}
.card[hidden] { display: none; }
.card h2 {
  margin: 0;
  font-family: var(--serif);
  font-size: 1.12rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  line-height: 1.15;
}
.card-kind {
  margin: 0.22rem 0 0.85rem;
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.card dl {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.42rem 0.9rem;
  font-size: 0.82rem;
}
.card dt {
  color: var(--ink-3);
  font-size: 0.65rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  align-self: center;
}
.card dd {
  margin: 0;
  text-align: right;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

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

/* the one action a card carries, and it asks twice */
.card-act {
  appearance: none;
  display: block;
  width: 100%;
  margin-top: 0.9rem;
  border: 1px solid rgba(150, 205, 230, 0.2);
  border-radius: 2px;
  background: none;
  padding: 0.42rem 0.4rem 0.4rem;
  font: inherit;
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  pointer-events: auto;
  transition: border-color 0.2s, color 0.2s, background 0.2s;
}
.card-act[hidden] { display: none; }
.card-act:hover { border-color: rgba(190, 232, 255, 0.6); color: var(--ink); }
.card-act:focus-visible { outline: 1px solid rgba(190, 232, 255, 0.8); outline-offset: 2px; }
.card-act.armed {
  border-color: rgba(255, 196, 106, 0.65);
  background: rgba(255, 196, 106, 0.08);
  color: rgba(255, 214, 150, 0.98);
  text-transform: none;
  letter-spacing: 0.02em;
}

.fallback {
  position: fixed;
  inset: 0;
  display: grid;
  place-content: center;
  padding: 2rem;
  max-width: 34rem;
  margin: auto;
  text-align: center;
  color: #cfe8f4;
}
.fallback[hidden] { display: none; }

/* ---- photo mode ----------------------------------------------------------------------
   Everything that lives above the water steps out of the shot at once. The tank keeps
   running underneath exactly as before, fish keep feeding and breeding behind an empty
   frame, because photo mode is a curtain drawn back and not a pause. */
body.photo #job,
body.photo #purse,
body.photo #notice,
body.photo #hint,
body.photo .appetite,
body.photo #shoptag,
body.photo #home,
body.photo #speaker,
body.photo .card,
body.photo .shop { opacity: 0; pointer-events: none; transition: opacity 0.45s ease; }
body.photo #tank { cursor: none; }
/* the single exception, and it is the line that says how to get the tank back */
body.photo #notice.through:not(.gone) { opacity: 1; }

/* ---- the ledger ------------------------------------------------------------------------
   The tank tab's rows are quieter than shop rows: no drawing, no price, a fact and its
   number set in the two faces everything else uses. */
.stat-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.62rem 0;
  border-bottom: 1px solid var(--rule-2);
  animation: row-in 0.34s cubic-bezier(0.2, 0.9, 0.25, 1) both;
}
.stat-row:last-of-type { border-bottom: 0; }
.stat-row span {
  font-size: 0.755rem;
  letter-spacing: 0.02em;
  color: var(--ink-3);
}
.stat-row b.coin {
  font-family: var(--pixel);
  font-size: 16px;
  line-height: 1;
  -webkit-font-smoothing: none;
  font-smooth: never;
  color: var(--ink);
}
.stat-row b.coin::before { display: none; }

/* A gold mark travels with the fish it belongs to, even onto a nursery label. */
.golden-row .shop-name { color: #ffd98f; }
.golden-row .shop-glyph { color: #ffd98f; opacity: 1; }
.golden-row .shop-glyph svg { filter: drop-shadow(0 0 6px rgba(255, 196, 106, 0.4)); }

@media (prefers-reduced-motion: reduce) {
  #hint { animation-delay: 0.2s; animation-duration: 0.3s; }
  #shoptag { animation: none; }
  .shop { animation: none; }
}

/* ---- the settings rows -----------------------------------------------------------------
   A control is a purchase with the price taken off, so it inherits every bit of the row
   above it and only has to say what the button is for. */
.shop-row.control .shop-buy.state {
  font-family: var(--ui, inherit);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  min-width: 5.4rem;
  color: rgba(214, 236, 248, 0.55);
}
.shop-row.control .shop-buy.state.lit { color: rgba(150, 230, 255, 0.95); }
.shop-row.control .shop-buy.state:hover { color: rgba(226, 245, 255, 1); }

/* ---- telling the two coins apart without colour ----------------------------------------
   A green dot and an orange dot are the exact pair a deuteranope cannot separate, and the
   two currencies in this tank were nothing but that pair. With this on, a frag is a ring
   and a young is a filled disc with a notch, so the shape carries the meaning and the
   colour is left to be decoration, which is all it should ever have been. */
body.marks .coin.frags::before {
  background: none;
  box-shadow: inset 0 0 0 2px var(--frag);
}
body.marks .coin.fry::before {
  border-radius: 0;
  transform: rotate(45deg);
  box-shadow: 0 0 6px rgba(255, 196, 106, 0.5);
}

/* ---- the captions, switched off ------------------------------------------------------- */
body.nocoach #hint { display: none; }

/* ---- the almanac rows ------------------------------------------------------------------
   A record and not a shelf, so there is no price and no button. The gold ones are marked
   because they are the reason anybody is reading this tab. */
.shop-row.book { cursor: default; }
.shop-row.book:hover { background: none; }
.shop-row.book.gold .shop-name { color: rgb(255, 214, 143); }
.shop-row.book.gold .shop-glyph { color: rgba(255, 206, 128, 0.85); }
.shop-row.book .shop-name { text-transform: none; }
