/* Fruit Match: the game's name and its button across the top, and under them the round's own
   area, which fruit-match.js lays the board out in. The panel's size is game-layout.css's
   (data-ideal); the stage fills it. Behind everything is a scene: --frm-sky is its picture,
   set by fruit-match.js. Every scene keeps its scenery along the bottom edge, so it is fitted
   from the bottom; data-scene names it, and the colour here is what shows until it arrives. */

.game-root[data-game="fruit-match"] {
  position: relative; display: block; padding: 0; overflow: hidden; text-align: left;
  background: #3d9bf5 var(--frm-sky, none) center bottom / cover no-repeat;
  touch-action: manipulation;
  -webkit-user-select: none; user-select: none;
}
.game-root[data-game="fruit-match"][data-scene="backdrop-stars"] { background-color: #232f9e; }
.game-root[data-game="fruit-match"][data-scene="backdrop-ocean"] { background-color: #1583d6; }
.game-root[data-game="fruit-match"][data-scene="backdrop-meadow"] { background-color: #94a3f6; }
.game-root[data-game="fruit-match"][data-scene="backdrop-sea"] { background-color: #12a4dc; }
.frm-stage { position: absolute; inset: 0; }

/* --- the top row: the game's name at the left, its button at the right ------------------------ */
.frm-top {
  position: absolute; top: 14px; left: 18px; right: 18px; z-index: 2;
  display: flex; align-items: baseline; gap: 10px; pointer-events: none; text-align: left;
}
.frm-game { font-weight: 700; color: #fff; text-shadow: 0 1px 2px rgba(12, 62, 122, .35); }
.frm-tools { position: absolute; top: 12px; right: 14px; z-index: 4; display: flex; gap: 8px; }
.frm-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border: 1px solid rgba(255, 255, 255, .6); border-radius: 999px;
  background: rgba(255, 255, 255, .82); color: #33506e;
  font: inherit; font-size: .85rem; cursor: pointer; white-space: nowrap;
}
.frm-pill:hover:not(:disabled) { border-color: var(--c-primary); color: var(--c-text); }
.frm-pill:disabled { opacity: .45; cursor: default; }
.frm-pill .frm-icon { width: 16px; height: 16px; }

/* --- the round's own area --------------------------------------------------------------------
   The top padding clears the row above. */
.frm {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 52px 6px 3px; box-sizing: border-box; overflow: hidden; text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.frm > .frm-hud, .frm > .frm-cap, .frm > .frm-ctrl { flex: none; }

/* The tries left, as hearts, at the board's left edge and two bars at its right, one over the
   other: how much of the level is cleared, marked 0 and 100% at its ends, and the level's time,
   marked 0 and its full length; each has its name after it. --bw is the board's width and --slack
   the space left over above, both set by fruit-match.js. The row's height is fixed: the board is
   laid out in what it leaves. The row is as wide as the board, and 304px where the board is
   narrower than that and the stage is not: the same width as the row of boxes under the board. */
.frm-hud {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: max(var(--bw, 100%), min(100%, 304px)); max-width: 100%; height: 1.84rem; margin-top: var(--slack, 0px); padding: 0 6px; box-sizing: border-box;
}
.frm-tries { flex: none; display: flex; align-items: center; gap: 3px; }
/* The heart's shape is 77% of its box's height: 30px makes it about as tall as the two bars. */
.frm-heart { display: block; width: 30px; height: 30px; overflow: visible; filter: drop-shadow(0 1px 1px rgba(12, 62, 122, .4)); }
.frm-heart path { fill: #ff4d6d; stroke: #fff; stroke-width: 2; stroke-linejoin: round; }
.frm-heart.is-off path { fill: rgba(12, 62, 122, .3); stroke: rgba(255, 255, 255, .8); }
.frm-heart.is-spent { animation: frm-spent .45s ease-out; }
@keyframes frm-spent {
  0% { transform: scale(1.5) rotate(-12deg); }
  35% { transform: scale(.8) rotate(8deg); }
  70% { transform: scale(1.1); }
}
/* A row each: the 0, the bar, its far end, its name. The first bar's fill is as wide as the share
   of the level's pairs joined; the second's as the share of the level's time left. The two rows
   and the gap between them come to 27px, inside the row's fixed height. */
.frm-bars {
  position: relative; flex: 0 1 260px; min-width: 0; display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 3px 5px;
}
.frm-hp-end, .frm-hp-name { color: #fff; font-size: .68rem; font-weight: 800; line-height: 1; text-shadow: 0 1px 2px rgba(12, 62, 122, .5); }
.frm-hp {
  min-width: 0; height: 12px; box-sizing: border-box; overflow: hidden;
  border: 2px solid #fff; border-radius: 999px; background: rgba(12, 62, 122, .4);
  box-shadow: 0 1px 2px rgba(12, 62, 122, .35);
}
.frm-hp-fill {
  display: block; width: 0; height: 100%; border-radius: 999px;
  background: linear-gradient(180deg, #ff9fb0 0 40%, #ff4d6d 40% 100%); transition: width .28s ease-out;
}
/* 0.1s is the step fruit-match.js moves the time bar by. */
.frm-time-fill { background: linear-gradient(180deg, #ffe9a3 0 40%, #ffb703 40% 100%); transition: width .1s linear; }
/* The time gained, floating up from the tip of the time bar's fill: fruit-match.js puts it there
   (left, top) and takes it away when this has played. */
.frm-time-plus {
  position: absolute; z-index: 1; pointer-events: none;
  color: #17a35a; font-size: 1.05rem; font-weight: 900; line-height: 1; white-space: nowrap;
  text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff, 0 2px 3px rgba(12, 62, 122, .5);
  animation: frm-time-plus .9s ease-out both;
}
@keyframes frm-time-plus {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.5); }
  20% { opacity: 1; transform: translate(-50%, -70%) scale(1.3); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -190%) scale(1); }
}
.frm-hp.is-bump { animation: frm-bump .28s ease-out; }
@keyframes frm-bump { 40% { transform: scale(1.08); } }

.frm-fit { flex: 1 1 0; min-height: 0; width: 100%; display: grid; place-items: start center; }
.frm-board { position: relative; }
/* A tile acts on a tap, so a finger's up-and-down move still scrolls the page. */
.frm-canvas {
  display: block; width: 100%; height: 100%; cursor: pointer; touch-action: pan-y;
  user-select: none; -webkit-user-select: none;
}

/* Two lines tall whatever it says, empty included: the board is laid out in what this leaves, so
   a caption that changed height would move the board as words come and go. It lies over a
   scene's bottom edge, pale cloud and sand as often as dark hills and deep water: dark words
   with a white halo read on all of them. */
.frm-cap {
  display: flex; align-items: center; justify-content: center; box-sizing: border-box;
  height: 3em; overflow: hidden; line-height: 1.5; margin: 0; width: 100%; max-width: 560px; padding: 0 8px;
  color: #0f3d6b; font-size: .86rem; font-weight: 700; text-align: center;
  text-shadow: 0 0 2px #fff, 0 0 6px rgba(255, 255, 255, .95), 0 0 10px rgba(255, 255, 255, .8);
}
/* Moves with the hand: 4.2s is DEMO.cycle in fruit-match.js; the two change together. */
.frm-cap.is-on { animation: frm-say 4.2s ease-in-out infinite; }
@keyframes frm-say {
  0%, 8% { transform: translateY(0); }
  14%, 48% { transform: translateY(-3px); color: #c2410c; }
  60%, 100% { transform: translateY(0); }
}

/* The lesson's hand. fruit-match.js places it with transform each frame; the offsets put the
   fingertip (34.4% 5.9% of the icon) on the point it is moved to. */
.frm-hand {
  position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none;
  width: 46px; aspect-ratio: 32 / 34; opacity: 0;
}
.frm-hand[hidden] { display: none; }
.frm-hand svg { display: block; width: 100%; height: 100%; }

/* Hint and Shuffle: two boxes under the caption, one 26px in from the board's left edge and one
   26px in from its right, each with a badge hung on its top right corner: how many are in hand,
   or a plus for none. The row is 10px taller than the speaker it is level with; the 3px it rises
   over the caption and the 7px less under it keep the board where it was. */
.frm-ctrl {
  position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between;
  width: max(var(--bw, 100%), min(100%, 304px)); max-width: 100%; min-height: 48px; margin-top: -3px; padding: 0 26px; box-sizing: border-box;
}
.frm-box {
  position: relative; display: grid; place-items: center; width: 72px; height: 48px; padding: 0; box-sizing: border-box;
  border: 2px solid #fff; border-radius: 16px; background: rgba(255, 255, 255, .82); cursor: pointer;
  box-shadow: 0 2px 0 rgba(12, 62, 122, .3);
}
.frm-box:hover:not(:disabled) { background: #fff; }
.frm-box:disabled { opacity: .5; cursor: default; }
.frm-tool-icon { display: block; width: 34px; height: 34px; }
.frm-plus {
  position: absolute; top: -5px; right: -10px; display: grid; place-items: center; min-width: 24px; height: 24px; padding: 0 5px; box-sizing: border-box;
  border: 2px solid #fff; border-radius: 999px; background: #2fb463; color: #fff;
  font-size: .84rem; font-weight: 800; line-height: 1;
  box-shadow: 0 1px 2px rgba(12, 62, 122, .35);
}
.frm-plus.is-pop { animation: frm-pop .4s ease-out; }
@keyframes frm-pop { 40% { transform: scale(1.6); } }
.frm-plus-icon { display: block; width: 12px; height: 12px; fill: none; stroke: #fff; stroke-width: 3.6; stroke-linecap: round; }

/* At the stage's two sides, halfway down; under the card's panel (z-index 5). */
.frm-arrow {
  position: absolute; top: 50%; z-index: 3; transform: translateY(-50%);
  display: grid; place-items: center; width: 42px; height: 42px; padding: 0;
  border: 0; border-radius: 50%; background: rgba(255, 255, 255, .62); color: #33506e; cursor: pointer;
  box-shadow: 0 1px 4px rgba(12, 62, 122, .2);
}
.frm-prev { left: 6px; }
.frm-next { right: 6px; }
.frm-arrow:hover:not(:disabled) { background: #fff; color: #0f3d6b; }
/* Faint on the icon, not the button: an opacity on the button would fade its tip with it. */
.frm-arrow:disabled { cursor: default; }
.frm-arrow:disabled .frm-icon { opacity: .12; }
.frm-arrow[hidden] { display: none; }
/* Where a press goes, beside the arrow on hover. */
.frm-arrow::after {
  content: attr(data-tip); position: absolute; top: 50%; transform: translateY(-50%);
  padding: 5px 10px; border-radius: 999px; background: rgba(255, 255, 255, .95); color: #4d4031;
  box-shadow: 0 1px 4px rgba(40, 30, 20, .18); font-size: .8rem; font-weight: 600; white-space: nowrap;
  pointer-events: none; opacity: 0; transition: opacity .12s ease;
}
.frm-prev::after { left: calc(100% + 4px); }
.frm-next::after { right: calc(100% + 4px); }
.frm-arrow:hover::after, .frm-arrow:focus-visible::after { opacity: 1; }
.frm-arrow .frm-icon { width: 28px; height: 28px; }
/* No room beside the board (fruit-match.js sets the class): halfway down, the arrows would lie
   over its outer tiles, so the two sit together left of the middle of the bottom row, between
   Hint and Shuffle. */
.frm-tight .frm-arrow { top: auto; bottom: 10px; transform: none; width: 34px; height: 34px; }
.frm-tight .frm-prev { left: calc(50% - 74px); }
.frm-tight .frm-next { left: calc(50% - 36px); right: auto; }
/* There the two boxes stand 160px apart, room for the arrows and the speaker between them: in a
   row wider than 304px they come in from its ends, and in a narrower one they give up width. */
.frm-tight .frm-ctrl { padding: 0 max(0px, calc((var(--bw) - 304px) / 2)); }
.frm-tight .frm-box { width: min(72px, calc((100% - 160px) / 2)); }
.frm-tight .frm-arrow::after { display: none; }
.frm-tight .frm-arrow .frm-icon { width: 24px; height: 24px; }

/* The speaker, and the dots beside it that open the menu. The dots take no room until shown
   (hover, focus, or the menu open); a screen that cannot hover shows them always, dimmer. The
   menu opens upward. */
.frm-round {
  width: 38px; height: 38px; padding: 0;
  display: grid; place-items: center; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .62); color: #4d4031; cursor: pointer;
  box-shadow: 0 1px 4px rgba(40, 30, 20, .18);
}
.frm-round:hover { background: #fff; }
.frm-round .frm-sicon { width: 22px; height: 22px; }
.frm-audio { position: absolute; right: 12px; bottom: 10px; z-index: 3; display: flex; align-items: center; }
/* Little room beside the board (fruit-match.js sets the classes): the corner is the right-hand
   box's, so the speaker stands in the middle of the bottom row, and right of the middle when the
   arrows are there too. .frm-tight comes with .frm-snug and after it: same specificity. */
.frm-snug .frm-audio { right: auto; left: 50%; transform: translateX(-50%); }
.frm-tight .frm-audio { left: calc(50% + 10px); bottom: 8px; transform: none; }
.frm-more {
  display: grid; place-items: center; width: 0; height: 38px; padding: 0; overflow: hidden;
  border: 0; background: none; color: rgba(77, 64, 49, .6); cursor: pointer; opacity: 0;
  transition: opacity .15s ease;
}
.frm-audio:hover .frm-more, .frm-audio:focus-within .frm-more, .frm-audio.is-open .frm-more { width: 30px; opacity: 1; }
@media (hover: none) { .frm-more { width: 26px; opacity: .6; } }
.frm-more .frm-sicon { width: 22px; height: 22px; }
.frm-ellipsis { stroke-width: 3.4; }
.frm-menu {
  position: absolute; right: 0; bottom: 46px; min-width: 200px; padding: 6px; box-sizing: border-box;
  border: 1px solid rgba(77, 64, 49, .18); border-radius: 12px; background: #fffdf8;
  box-shadow: 0 6px 20px rgba(50, 40, 20, .18);
}
.frm-menu[hidden] { display: none; }
.frm-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; width: 100%; padding: 9px 10px;
  border: 0; border-radius: 8px; background: none; color: #4d4031; font: inherit; font-size: .88rem; font-weight: 600; cursor: pointer; text-align: left;
}
.frm-opt:hover, .frm-opt:focus-visible { background: rgba(77, 64, 49, .07); }
.frm-sw { position: relative; flex: none; width: 34px; height: 20px; border-radius: 999px; background: rgba(77, 64, 49, .22); transition: background .15s ease; }
.frm-sw::after {
  content: ''; position: absolute; left: 2px; top: 2px; width: 16px; height: 16px; border-radius: 50%;
  background: #fff; transition: transform .15s ease;
}
.frm-opt[aria-checked="true"] .frm-sw { background: #4fb878; }
.frm-opt[aria-checked="true"] .frm-sw::after { transform: translateX(14px); }
.frm-sicon { display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.frm-cone { fill: currentColor; stroke: none; }
.frm-sound.off .frm-waves { display: none; }
.frm-sound:not(.off) .frm-slash { display: none; }
.frm-icon { width: 18px; height: 18px; flex: none; }

/* --- over the stage: the panel dims it, and a sheet in its middle holds the card -------------- */
.frm-win { position: absolute; inset: 0; z-index: 5; pointer-events: none; }
.frm-panel {
  position: absolute; inset: 0; pointer-events: auto;
  display: flex; flex-direction: column; align-items: center; gap: 18px;
  padding: 20px; text-align: center; overflow-y: auto;
  background: rgba(20, 84, 156, .6);
  animation: frm-in .35s ease-out;
}
@keyframes frm-in { from { opacity: 0; } }
/* Centred with auto margins rather than justify-content: a sheet taller than the stage scrolls
   from its top instead of losing it. */
.frm-panel > * { flex: none; }
.frm-panel > :first-child { margin-top: auto; margin-bottom: auto; }
.frm-sheet {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; width: min(440px, 100%); box-sizing: border-box;
  padding: 26px 18px; border-radius: 20px; background: #fffdf8;
  box-shadow: 0 10px 0 rgba(77, 64, 49, .08);
}
.frm-sheet .frm-title { margin: 0; font-size: 1.6rem; font-weight: 700; color: #4d4031; }
/* Each letter's delay is set by fruit-match.js. */
.frm-word { white-space: nowrap; }
.frm-ch { display: inline-block; animation: frm-wave .5s ease-in-out both; }
@keyframes frm-wave { 40% { transform: translateY(-.35em); } }
.frm-view { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; }
.frm-view p { margin: 0; }
.frm-view-title { font-weight: 800; color: #4d4031; }
.frm-view-line { color: #4d4031; }
.frm-view-small { font-size: .8rem; color: #9a8c78; }
/* The fruit the next level adds, on a tile of its own. */
.frm-new { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 0; color: #4d4031; font-weight: 700; }
.frm-new-tile {
  flex: none; display: grid; place-items: center; width: 46px; height: 44px; border-radius: 9px;
  background: #d2f4e8; box-shadow: 0 3px 0 #6fbfa9;
  animation: frm-badge-in .55s cubic-bezier(.2, .9, .3, 1.35) .5s both;
}
.frm-new-tile img { display: block; width: 32px; height: 32px; object-fit: contain; }
.frm-ask { display: flex; flex-direction: column; align-items: center; gap: 10px; color: #6a5a44; }
.frm-ask p { margin: 0; }
.frm-moods { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.frm-mood {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px;
  border: 1px solid var(--c-border); border-radius: 999px; background: #fff; color: var(--c-text);
  font: inherit; cursor: pointer;
}
.frm-mood:hover { border-color: var(--c-primary); }
.frm-mood.on { background: var(--c-primary); border-color: var(--c-primary); color: #fff; }
.frm-mood .frm-icon { width: 22px; height: 22px; }
.frm-ask .frm-note { min-height: 1.3em; margin: 0; font-size: .9rem; color: var(--c-text-soft); }
.frm-key {
  display: inline-block; min-width: 1.6em; padding: 1px 6px; margin: 0 1px;
  border: 1px solid #c9ced8; border-bottom-width: 2px; border-radius: 5px; background: #fff;
  font: inherit; font-size: .85em; font-weight: 700; line-height: 1.4; text-align: center; color: var(--c-text);
}
.frm-choices { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.frm-choices .btn { display: inline-flex; align-items: center; gap: 8px; }
.frm-choices .frm-icon { stroke-width: 2.2; }
/* The last level's award: a green badge that pops in. */
.frm-badge {
  display: inline-flex; align-items: center; gap: 8px; margin: 0;
  padding: 7px 18px 7px 13px; border-radius: 999px;
  background: #dff3e6; border: 1.5px solid #8fd3a9;
  color: #237a4a; font-size: 1.12rem; font-weight: 800;
  animation: frm-badge-in .55s cubic-bezier(.2, .9, .3, 1.35) .15s both;
}
.frm-cap-icon { flex: none; width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.frm-cap-top { fill: currentColor; }
@keyframes frm-badge-in { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }

/* The review build's tools, under the game panel and outside it. */
.frm-review {
  display: flex; gap: 8px; justify-content: center; align-items: center; flex-wrap: wrap;
  margin: 10px auto 0; padding: 8px; font-size: .85rem; color: #4a5766;
}
.frm-review select, .frm-review button { font: inherit; padding: 4px 8px; border-radius: 8px; border: 1px solid #ccc; background: #fff; }

/* #game-root itself is the element that goes full screen; these same rules are the
   fixed-position fallback for a browser without the Fullscreen API. game-layout.css gives a
   [data-ideal] panel an explicit width and height, which would beat the fallback's inset. */
#game-root.frm-fs {
  position: fixed; inset: 0; z-index: 200; margin: 0; padding: 0;
  width: auto; height: auto; max-width: none;
  border: 0; border-radius: 0; box-shadow: none; min-height: 0; overflow: hidden;
}
body.frm-locked { overflow: hidden; }
