kgames

KGames — free keyboard games for kids
git clone https://www.keyboard.games/code/kgames.git
Log | Files | Refs | README | LICENSE

style.css (29445B)


      1 /* Story Stamp — DOM game styles. Everything scales from --u (1% of the shorter
      2    side of #game-container) so the library looks the same on a phone and a TV. */
      3 
      4 * { margin: 0; padding: 0; box-sizing: border-box; }
      5 html, body { height: 100%; overflow: hidden; }
      6 body {
      7   background: #1A1A2E;
      8   font-family: 'Fredoka', sans-serif;
      9   display: flex;
     10   flex-direction: column;
     11   color: #1A1A2E;
     12 }
     13 nav { width: 100%; padding: 0.6rem 1.25rem; flex-shrink: 0; }
     14 nav a { color: #aaa; text-decoration: none; font-size: 1rem; }
     15 nav a:hover { color: #fff; }
     16 #game-container { flex: 1; width: 100%; min-height: 0; position: relative; overflow: hidden; }
     17 
     18 #audio-controls { position: fixed; top: 0.45rem; right: 1rem; display: flex; gap: 0.4rem; z-index: 10; }
     19 #audio-controls button {
     20   background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.18); color: #bbb;
     21   font-family: 'Fredoka', sans-serif; font-size: 0.85rem; padding: 0.25rem 0.65rem; border-radius: 6px;
     22   cursor: pointer; user-select: none;
     23 }
     24 #audio-controls button:hover { background: rgba(255,255,255,0.16); color: #fff; }
     25 #audio-controls button.muted { color: #555; border-color: rgba(255,255,255,0.08); }
     26 
     27 #attribution {
     28   flex-shrink: 0; text-align: center; font-size: 0.65rem; color: #556; padding: 0.25rem 0.5rem 0.35rem;
     29   white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
     30 }
     31 #attribution a { color: #778; text-decoration: none; }
     32 #attribution a:hover { color: #aab; }
     33 
     34 /* ── Scene ────────────────────────────────────────────────────────────────── */
     35 .ss-root {
     36   --u: 5px;                 /* set by JS: 1% of min(width, height * 1.25) */
     37   --red: #E63946; --blue: #1D7CF2; --yellow: #FFD23F; --teal: #2EC4B6;
     38   --wood: #b7743c; --wood-dark: #8a5227; --wood-light: #d9975a;
     39   position: absolute; inset: 0; overflow: hidden; user-select: none;
     40   background: #f6e7c6;
     41   font-size: calc(var(--u) * 3.2);
     42 }
     43 .ss-root.ss-dusk { background: #e8c9a0; }
     44 .ss-root.ss-dusk .ss-wall { filter: saturate(0.85) brightness(0.92); }
     45 .ss-img { display: inline-block; width: 1em; height: 1em; vertical-align: -0.15em; object-fit: contain; }
     46 .ss-root.shake { animation: ss-shake 0.35s; }
     47 @keyframes ss-shake { 20% { transform: translateY(calc(var(--u) * 0.5)); } 50% { transform: translateY(calc(var(--u) * -0.3)); } }
     48 
     49 /* wall + window */
     50 .ss-wall { position: absolute; left: 0; right: 0; top: 0; height: 62%;
     51   background: linear-gradient(#fff6de, #f3e0b8); }
     52 .ss-wall::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: calc(var(--u) * 1.6);
     53   background: var(--wood-dark); box-shadow: 0 calc(var(--u) * -0.6) 0 var(--wood-light); }
     54 .ss-window { position: absolute; left: 50%; top: 4%; width: calc(var(--u) * 34); height: calc(var(--u) * 26); transform: translateX(-50%);
     55   border-radius: calc(var(--u) * 17) calc(var(--u) * 17) calc(var(--u) * 1.5) calc(var(--u) * 1.5); overflow: hidden;
     56   border: calc(var(--u) * 1.4) solid var(--wood); box-shadow: 0 0 0 calc(var(--u) * 0.5) var(--wood-light), inset 0 0 calc(var(--u) * 2) rgba(0,0,0,0.15);
     57   background: #8fdcff; }
     58 .ss-window::after { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: calc(var(--u) * 1); margin-left: calc(var(--u) * -0.5); background: var(--wood); opacity: 0.9; }
     59 .ss-sky { position: absolute; inset: 0; background: linear-gradient(#7fd3ff, #c8efff 70%); }
     60 .ss-sun { position: absolute; right: 14%; top: 10%; width: calc(var(--u) * 7); height: calc(var(--u) * 7);
     61   border-radius: 50%; background: radial-gradient(circle, #fff6c2 0%, #FFD23F 55%, rgba(255,210,63,0) 72%); }
     62 .ss-cloud { position: absolute; top: 18%; width: calc(var(--u) * 9); height: calc(var(--u) * 3); background: #fff;
     63   border-radius: 999px; opacity: 0.9; animation: ss-drift 40s linear infinite; }
     64 .ss-cloud::before { content: ''; position: absolute; left: 25%; top: -50%; width: 45%; height: 130%; background: #fff; border-radius: 50%; }
     65 .ss-cloud.c2 { top: 32%; width: calc(var(--u) * 6); animation-duration: 55s; animation-delay: -20s; }
     66 @keyframes ss-drift { from { transform: translateX(-60%); } to { transform: translateX(400%); } }
     67 .ss-sea { position: absolute; left: 0; right: 0; bottom: 0; height: 34%; background: linear-gradient(#3fb9e8, #1D7CF2); }
     68 .ss-sea::after { content: ''; position: absolute; inset: 0;
     69   background: repeating-linear-gradient(90deg, rgba(255,255,255,0.18) 0 6%, transparent 6% 14%);
     70   mask: linear-gradient(transparent, rgba(0,0,0,0.6)); -webkit-mask: linear-gradient(transparent, rgba(0,0,0,0.6)); }
     71 .ss-boat { position: absolute; top: 4%; font-size: calc(var(--u) * 4); animation: ss-sail 30s linear infinite; }
     72 @keyframes ss-sail { from { transform: translateX(-120%); } 50% { transform: translateX(400%); } 50.01% { transform: translateX(-120%) scaleX(-1); } to { transform: translateX(400%) scaleX(-1); } }
     73 .ss-bird { position: absolute; top: 22%; font-size: calc(var(--u) * 2); animation: ss-fly 18s linear infinite; }
     74 @keyframes ss-fly { from { transform: translateX(1500%) translateY(0); } 50% { transform: translateX(700%) translateY(-60%); } to { transform: translateX(-200%) translateY(0); } }
     75 .ss-palm { position: absolute; left: 4%; bottom: 26%; font-size: calc(var(--u) * 9); transform-origin: 50% 100%; animation: ss-sway 5s ease-in-out infinite; }
     76 @keyframes ss-sway { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(2.5deg); } }
     77 .ss-walkers { position: absolute; left: 0; right: 0; bottom: 28%; height: 1px; }
     78 .ss-walker { position: absolute; bottom: 0; font-size: calc(var(--u) * 4); transition: transform 14s linear; will-change: transform; }
     79 
     80 /* shelves */
     81 .ss-shelf { position: absolute; top: 5%; width: calc(var(--u) * 26); height: 84%; display: flex; flex-direction: column; justify-content: space-between;
     82   background: var(--wood); border-radius: calc(var(--u) * 1); padding: calc(var(--u) * 1.2); box-shadow: inset 0 0 0 calc(var(--u) * 0.5) var(--wood-dark); }
     83 .ss-shelf.left { left: 2%; } .ss-shelf.right { right: 2%; }
     84 .ss-row { flex: 1; margin-bottom: calc(var(--u) * 1.2); background: #6b3f1d; border-radius: calc(var(--u) * 0.5); position: relative;
     85   box-shadow: 0 calc(var(--u) * 0.8) 0 var(--wood-light); }
     86 .ss-row:last-child { margin-bottom: 0; }
     87 .ss-spines { position: absolute; left: 6%; right: 6%; bottom: 0; top: 10%; display: flex; align-items: flex-end; gap: 3%; }
     88 .ss-spines i { flex: 1; border-radius: calc(var(--u) * 0.4) calc(var(--u) * 0.4) 0 0; box-shadow: inset calc(var(--u) * -0.4) 0 rgba(0,0,0,0.18); }
     89 .ss-sign { position: absolute; left: 50%; top: 58%; transform: translateX(-50%) rotate(-1.5deg); background: #fff; color: var(--red);
     90   padding: 0.05em 0.6em; border-radius: 0.4em; font-weight: 600; font-size: calc(var(--u) * 3.2); border: calc(var(--u) * 0.45) solid var(--yellow);
     91   white-space: nowrap; box-shadow: 0 calc(var(--u) * 0.5) 0 rgba(0,0,0,0.12); }
     92 
     93 /* decor (library upgrades) */
     94 .ss-decor { position: absolute; inset: 0; pointer-events: none; }
     95 .ss-decor > * { position: absolute; font-size: calc(var(--u) * 5); }
     96 .ss-decor .d-rug { left: 50%; top: 106%; width: calc(var(--u) * 70); height: calc(var(--u) * 14); transform: translateX(-50%); border-radius: 50%;
     97   background: repeating-radial-gradient(ellipse, var(--red) 0 8%, var(--yellow) 8% 16%, var(--teal) 16% 24%); opacity: 0.75; font-size: 1px; }
     98 .ss-decor .d-plant { left: 26%; bottom: 3%; font-size: calc(var(--u) * 7); }
     99 .ss-decor .d-lamp { right: 27%; bottom: 40%; animation: ss-twinkle 2.4s ease-in-out infinite; }
    100 .ss-decor .d-tank { right: 26%; bottom: 3%; width: calc(var(--u) * 12); height: calc(var(--u) * 8); background: linear-gradient(#bfefff, #4fc3f7);
    101   border: calc(var(--u) * 0.6) solid var(--wood-dark); border-radius: calc(var(--u) * 1); font-size: calc(var(--u) * 3.5); overflow: hidden; }
    102 .ss-decor .d-tank .ss-img { position: absolute; top: 30%; animation: ss-swimby 6s ease-in-out infinite alternate; }
    103 .ss-decor .d-tank .ss-img + .ss-img { top: 55%; animation-duration: 8s; animation-direction: alternate-reverse; }
    104 @keyframes ss-swimby { from { left: 5%; transform: scaleX(1); } to { left: 60%; transform: scaleX(1); } }
    105 .ss-decor .d-bunting { left: 8%; right: 8%; top: 1%; height: calc(var(--u) * 3); font-size: 1px;
    106   background: repeating-linear-gradient(90deg, var(--yellow) 0 8%, var(--teal) 8% 16%, var(--red) 16% 24%, var(--blue) 24% 32%);
    107   clip-path: polygon(0 0, 100% 0, 100% 30%, 96% 100%, 92% 30%, 88% 100%, 84% 30%, 80% 100%, 76% 30%, 72% 100%, 68% 30%, 64% 100%, 60% 30%, 56% 100%, 52% 30%, 48% 100%, 44% 30%, 40% 100%, 36% 30%, 32% 100%, 28% 30%, 24% 100%, 20% 30%, 16% 100%, 12% 30%, 8% 100%, 4% 30%, 0 100%); }
    108 .ss-decor .d-cat { left: 30%; top: 96%; font-size: calc(var(--u) * 4.5); }
    109 .ss-decor .d-globe { left: 6%; top: 3%; font-size: calc(var(--u) * 4.5); animation: ss-spin 12s linear infinite; }
    110 .ss-decor .d-telescope { right: 5%; bottom: 2%; font-size: calc(var(--u) * 6); }
    111 .ss-decor .d-dino { left: 31%; top: 5%; font-size: calc(var(--u) * 8); filter: grayscale(1) brightness(1.3); }
    112 .ss-decor .d-rocket { right: 32%; top: 4%; font-size: calc(var(--u) * 5); animation: ss-bob 2.2s ease-in-out infinite; }
    113 @keyframes ss-twinkle { 50% { opacity: 0.55; } }
    114 @keyframes ss-spin { from { transform: rotateY(0); } to { transform: rotateY(360deg); } }
    115 @keyframes ss-bob { 50% { transform: translateY(-10%); } }
    116 
    117 /* floor */
    118 .ss-floor { position: absolute; left: 0; right: 0; top: 62%; bottom: 0;
    119   background: repeating-linear-gradient(90deg, #d9a06a 0 9%, #cf9560 9% 10%), #d9a06a; }
    120 .ss-floor::before { content: ''; position: absolute; inset: 0; background: linear-gradient(rgba(0,0,0,0.08), transparent 30%); }
    121 
    122 /* ── The queue ───────────────────────────────────────────────────────────── */
    123 .ss-queue { position: absolute; left: 2%; bottom: 20%; display: flex; gap: calc(var(--u) * 1.5); align-items: flex-end; z-index: 1; }
    124 .ss-patron { position: relative; width: calc(var(--u) * 12); text-align: center; transition: transform 0.25s, opacity 0.4s; }
    125 .ss-patron.in { animation: ss-pop 0.5s both; }
    126 .ss-patron-body { font-size: calc(var(--u) * 9); line-height: 1; filter: drop-shadow(0 calc(var(--u) * 0.6) 0 rgba(0,0,0,0.15)); transition: transform 0.25s; }
    127 .ss-patron.sel { transform: translateY(calc(var(--u) * -1.5)); }
    128 .ss-patron.sel .ss-patron-body { animation: ss-bounce 0.9s ease-in-out infinite; }
    129 .ss-patron-name { display: inline-block; margin-top: calc(var(--u) * 0.4); background: var(--c, #555); color: #fff; font-weight: 600; font-size: calc(var(--u) * 2.4);
    130   padding: 0 0.6em; border-radius: 999px; }
    131 .ss-patron .ss-num { position: absolute; left: calc(var(--u) * -0.5); top: calc(var(--u) * -1); }
    132 .ss-sign-card { display: inline-flex; flex-direction: column; align-items: center; background: #fff; border: calc(var(--u) * 0.45) solid #999; border-radius: calc(var(--u) * 1.2);
    133   padding: calc(var(--u) * 0.5) calc(var(--u) * 1); margin-bottom: calc(var(--u) * 0.8); font-size: calc(var(--u) * 5); line-height: 1; opacity: 0.75; transition: transform 0.25s, opacity 0.25s;
    134   box-shadow: 0 calc(var(--u) * 0.4) 0 rgba(0,0,0,0.12); }
    135 .ss-sign-card span { font-size: calc(var(--u) * 2.2); font-weight: 600; color: #333; margin-top: calc(var(--u) * 0.4); white-space: nowrap; }
    136 .ss-patron.sel .ss-sign-card { opacity: 1; transform: scale(1.12); }
    137 .ss-holding { position: absolute; right: calc(var(--u) * -1); bottom: calc(var(--u) * 6); font-size: calc(var(--u) * 4); background: #fff; border-radius: 0.3em; padding: 0.1em;
    138   transform: rotate(8deg); box-shadow: 0 0.1em 0 rgba(0,0,0,0.15); }
    139 .ss-patron.wait { opacity: 0.4; }
    140 .ss-patron.called { transform: translateX(calc(var(--u) * 20)) scale(1.05); opacity: 0; }
    141 @keyframes ss-bounce { 50% { transform: translateY(-6%); } }
    142 @keyframes ss-pop { from { transform: translateY(20%) scale(0.85); opacity: 0.4; } to { transform: none; opacity: 1; } }
    143 
    144 /* the patron at the desk */
    145 .ss-customer { position: absolute; right: 5%; bottom: 22%; width: calc(var(--u) * 16); text-align: center;
    146   transform: translateX(150%); transition: transform 0.9s cubic-bezier(.3,1.2,.5,1); }
    147 .ss-customer.in { transform: none; }
    148 .ss-customer.out { transform: translateX(150%); transition-duration: 0.8s; }
    149 .ss-cust-body { font-size: calc(var(--u) * 12); line-height: 1; filter: drop-shadow(0 calc(var(--u) * 0.6) 0 rgba(0,0,0,0.15)); }
    150 .ss-customer.in .ss-cust-body { animation: ss-bob 2.2s ease-in-out infinite; }
    151 .ss-customer.happy .ss-cust-body { animation: ss-jump 0.5s ease-in-out 2; }
    152 .ss-customer.puzzled .ss-cust-body { animation: ss-wobble 0.6s ease-in-out; }
    153 @keyframes ss-jump { 50% { transform: translateY(-18%); } }
    154 @keyframes ss-wobble { 25% { transform: rotate(-8deg); } 75% { transform: rotate(8deg); } }
    155 .ss-cust-name { display: inline-block; margin-top: calc(var(--u) * 0.4); color: #fff; font-weight: 600; font-size: calc(var(--u) * 2.6); padding: 0 0.6em; border-radius: 999px; }
    156 .ss-bubble { position: absolute; left: 50%; bottom: 100%; transform: translate(-50%, 10%) scale(0.6); opacity: 0; transition: transform 0.3s, opacity 0.3s;
    157   background: #fff; border-radius: calc(var(--u) * 2); padding: calc(var(--u) * 0.8) calc(var(--u) * 1.4); font-size: calc(var(--u) * 6); line-height: 1;
    158   box-shadow: 0 calc(var(--u) * 0.5) 0 rgba(0,0,0,0.12); white-space: nowrap; }
    159 .ss-bubble::after { content: ''; position: absolute; left: 50%; top: 100%; border: calc(var(--u) * 1.2) solid transparent; border-top-color: #fff; margin-left: calc(var(--u) * -1.2); }
    160 .ss-bubble.show { opacity: 1; transform: translate(-50%, -10%) scale(1); }
    161 
    162 /* ── Desk ────────────────────────────────────────────────────────────────── */
    163 .ss-desk { position: absolute; left: 54%; bottom: 2%; width: calc(var(--u) * 52); height: calc(var(--u) * 24); transform: translateX(-50%); }
    164 .ss-desk-top { position: absolute; left: -3%; right: -3%; top: 0; height: 18%; background: var(--wood-light); border-radius: calc(var(--u) * 1);
    165   box-shadow: 0 calc(var(--u) * 0.6) 0 var(--wood-dark); }
    166 .ss-desk-front { position: absolute; left: 0; right: 0; top: 16%; bottom: 0; background: var(--wood); border-radius: 0 0 calc(var(--u) * 1.2) calc(var(--u) * 1.2);
    167   background-image: repeating-linear-gradient(90deg, transparent 0 24%, rgba(0,0,0,0.1) 24% 25%); }
    168 .ss-desk-front::after { content: '📚'; position: absolute; right: 4%; bottom: 8%; font-size: calc(var(--u) * 3); opacity: 0.6; }
    169 
    170 /* request slip with sound boxes */
    171 .ss-slip { position: absolute; left: 50%; bottom: 70%; transform: translate(-50%, 30%) rotate(-6deg) scale(0.7); opacity: 0;
    172   background: #fffdf5; border-radius: calc(var(--u) * 1); padding: calc(var(--u) * 1.4) calc(var(--u) * 2.2) calc(var(--u) * 2.6);
    173   box-shadow: 0 calc(var(--u) * 0.6) 0 rgba(0,0,0,0.12), 0 0 0 calc(var(--u) * 0.3) #e8dcc0; transition: transform 0.4s cubic-bezier(.3,1.3,.5,1), opacity 0.3s;
    174   min-width: calc(var(--u) * 24); }
    175 .ss-slip.show { opacity: 1; transform: translate(-50%, 0) rotate(-2deg); }
    176 .ss-slip.ready { box-shadow: 0 0 0 calc(var(--u) * 0.6) var(--yellow), 0 calc(var(--u) * 0.6) 0 rgba(0,0,0,0.12); animation: ss-glow 1.2s ease-in-out infinite; }
    177 .ss-slip.wobble { animation: ss-wobble 0.5s; }
    178 .ss-desk.choosing .ss-slip.show { transform: translate(-118%, 0) rotate(-8deg) scale(0.8); }
    179 .ss-desk.choosing .ss-slip .ss-finger { display: none; }
    180 @keyframes ss-glow { 50% { box-shadow: 0 0 0 calc(var(--u) * 1.2) rgba(255,210,63,0.5), 0 calc(var(--u) * 0.6) 0 rgba(0,0,0,0.12); } }
    181 .ss-slip-title { font-size: calc(var(--u) * 2); color: #98876a; letter-spacing: 0.1em; text-transform: uppercase; text-align: center; margin-bottom: calc(var(--u) * 0.8); }
    182 .ss-boxes { display: flex; justify-content: center; gap: calc(var(--u) * 1.6); transition: gap 0.5s; }
    183 .ss-boxes.pass1 { gap: calc(var(--u) * 0.9); }
    184 .ss-boxes.pass2, .ss-boxes.fused { gap: calc(var(--u) * 0.3); }
    185 .ss-box { width: calc(var(--u) * 8); height: calc(var(--u) * 9); border: calc(var(--u) * 0.6) dashed #b9ab8c; border-radius: calc(var(--u) * 1.2);
    186   display: flex; align-items: center; justify-content: center; font-size: calc(var(--u) * 5.6); font-weight: 600; color: #b9ab8c; background: #fff;
    187   transition: transform 0.2s, background 0.2s, color 0.2s, border-color 0.2s; position: relative; }
    188 .ss-box.wide { width: calc(var(--u) * 12); }
    189 .ss-box.next { border-color: var(--c); color: #cfc4a8; transform: scale(1.06); animation: ss-nudge 1.4s ease-in-out infinite; }
    190 @keyframes ss-nudge { 50% { transform: scale(1.12); } }
    191 .ss-box .ss-partial { color: var(--c); }
    192 .ss-box.done { border-style: solid; border-color: var(--c); color: #fff; background: var(--c); }
    193 .ss-box.stamped { animation: ss-stampin 0.35s cubic-bezier(.3,1.5,.5,1); transform: rotate(-3deg); }
    194 .ss-box.stamped:nth-child(even) { transform: rotate(3deg); }
    195 @keyframes ss-stampin { from { transform: scale(1.8) rotate(-10deg); opacity: 0.3; } 60% { transform: scale(0.9) rotate(2deg); } to { transform: scale(1) rotate(-3deg); opacity: 1; } }
    196 .ss-box.hidden-letter { color: transparent; }
    197 .ss-box.hidden-letter::after { content: '?'; position: absolute; color: #d8cdb0; }
    198 .ss-box.hidden-letter.reveal { color: #fff; background: var(--c); border-color: var(--c); }
    199 .ss-box.hidden-letter.reveal::after { display: none; }
    200 .ss-box.speaking { transform: scale(1.22) !important; box-shadow: 0 0 0 calc(var(--u) * 0.8) rgba(255,210,63,0.7); z-index: 1; }
    201 .ss-box.hint { animation: ss-wobble 0.5s; border-color: var(--red); }
    202 .ss-finger { position: absolute; left: 10%; bottom: calc(var(--u) * -3.2); font-size: calc(var(--u) * 5); transform: translateX(-50%); opacity: 0; transition: left 0.18s ease-out, opacity 0.2s; pointer-events: none; }
    203 .ss-finger.show { opacity: 1; }
    204 
    205 /* the rubber stamp */
    206 .ss-stamp { position: absolute; right: calc(var(--u) * -8); bottom: 74%; width: calc(var(--u) * 8); height: calc(var(--u) * 9); transition: transform 0.35s cubic-bezier(.3,1.2,.5,1); transform-origin: 50% 100%; z-index: 3; }
    207 .ss-stamp-handle { position: absolute; left: 30%; width: 40%; top: 0; height: 55%; background: linear-gradient(90deg, #8a5227, #c98a4b, #8a5227); border-radius: 40% 40% 20% 20%; }
    208 .ss-stamp-base { position: absolute; left: 0; right: 0; bottom: 0; height: 40%; background: linear-gradient(#444, #222); border-radius: calc(var(--u) * 0.8); }
    209 .ss-stamp-base::after { content: ''; position: absolute; left: 8%; right: 8%; bottom: -14%; height: 18%; background: var(--red); border-radius: 30%; opacity: 0.8; }
    210 .ss-stamp.press { animation: ss-press 0.25s; }
    211 @keyframes ss-press { 40% { transform: translateY(18%) scaleY(0.9); } }
    212 .ss-stamp.over { transform: translate(calc(var(--u) * -30), calc(var(--u) * -19)) scale(1.3) rotate(-6deg); }
    213 .ss-stamp.over.slam { transform: translate(calc(var(--u) * -30), calc(var(--u) * -10)) scale(1.3) rotate(-2deg); transition-duration: 0.12s; transition-timing-function: cubic-bezier(.5,0,.8,.3); }
    214 
    215 /* the book cart */
    216 .ss-cart { position: absolute; left: 50%; bottom: 95%; transform: translate(-50%, 40%); opacity: 0; display: flex; gap: calc(var(--u) * 2.2); align-items: flex-end;
    217   padding: calc(var(--u) * 1.2) calc(var(--u) * 2) calc(var(--u) * 1.4); background: #cfd8dc; border-radius: calc(var(--u) * 1); transition: transform 0.45s cubic-bezier(.3,1.2,.5,1), opacity 0.3s;
    218   box-shadow: 0 calc(var(--u) * 0.6) 0 #90a4ae; z-index: 2; }
    219 .ss-cart::before, .ss-cart::after { content: ''; position: absolute; bottom: calc(var(--u) * -1.6); width: calc(var(--u) * 2.4); height: calc(var(--u) * 2.4); border-radius: 50%; background: #37474f; box-shadow: inset 0 0 0 calc(var(--u) * 0.5) #90a4ae; }
    220 .ss-cart::before { left: 8%; } .ss-cart::after { right: 8%; }
    221 .ss-cart.show { opacity: 1; transform: translate(-50%, 0); }
    222 .ss-cart.picked { background: transparent; box-shadow: none; }
    223 .ss-cart.picked::before, .ss-cart.picked::after { display: none; }
    224 .ss-book { position: relative; width: calc(var(--u) * 12); height: calc(var(--u) * 14); border-radius: calc(var(--u) * 0.6) calc(var(--u) * 1.2) calc(var(--u) * 1.2) calc(var(--u) * 0.6);
    225   background: var(--c); box-shadow: inset calc(var(--u) * 1.4) 0 0 rgba(0,0,0,0.22), inset calc(var(--u) * 1.8) 0 0 rgba(255,255,255,0.25), 0 calc(var(--u) * 0.5) 0 rgba(0,0,0,0.2);
    226   transition: transform 0.2s, opacity 0.4s; }
    227 .ss-cover { position: absolute; left: 24%; right: 10%; top: 12%; bottom: 12%; background: #fff; border-radius: calc(var(--u) * 0.6); display: flex; align-items: center; justify-content: center;
    228   font-size: calc(var(--u) * 6.5); line-height: 1; }
    229 .ss-book.sel { transform: translateY(-10%) scale(1.12); box-shadow: 0 0 0 calc(var(--u) * 0.6) var(--yellow), 0 calc(var(--u) * 0.5) 0 rgba(0,0,0,0.2); z-index: 1; }
    230 .ss-book.yes { animation: ss-jump 0.4s; }
    231 .ss-book.no { animation: ss-wobble 0.5s; filter: grayscale(0.6); }
    232 .ss-book.point { animation: ss-bounce 0.7s ease-in-out infinite; }
    233 .ss-book.gone { opacity: 0; transform: translateY(20%) scale(0.8); }
    234 .ss-book.stamped .ss-cover::after { content: 'OUT'; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(-18deg); color: var(--red);
    235   border: calc(var(--u) * 0.5) solid var(--red); border-radius: calc(var(--u) * 0.8); padding: 0 0.25em; font-size: calc(var(--u) * 3.2); font-weight: 600; letter-spacing: 0.05em;
    236   opacity: 0.85; animation: ss-stampin 0.3s; background: rgba(255,255,255,0.7); }
    237 .ss-book.handed { transform: translate(calc(var(--u) * 30), calc(var(--u) * -4)) scale(0.75) rotate(10deg); transition: transform 0.6s cubic-bezier(.4,0,.6,1); }
    238 .ss-book .ss-num { right: calc(var(--u) * -1); top: calc(var(--u) * -1); left: auto; bottom: auto; }
    239 .ss-num { position: absolute; width: calc(var(--u) * 3.2); height: calc(var(--u) * 3.2); border-radius: 50%; background: #1A1A2E; color: #fff; font-size: calc(var(--u) * 2);
    240   display: flex; align-items: center; justify-content: center; font-weight: 600; }
    241 .ss-book-out { position: absolute; left: 50%; bottom: 95%; transform: translate(-50%, 0); opacity: 0; transition: transform 0.7s cubic-bezier(.4,0,.6,1), opacity 0.3s; z-index: 2; }
    242 .ss-book-out.show { opacity: 1; }
    243 .ss-book-out.fly { transform: translate(calc(var(--u) * -44), calc(var(--u) * -40)) scale(0.35) rotate(-20deg); opacity: 0.6; }
    244 
    245 /* ── Prompt / HUD ────────────────────────────────────────────────────────── */
    246 .ss-prompt { position: absolute; left: 50%; bottom: 4%; transform: translateX(-50%); background: #1A1A2E; color: #fff; padding: 0.25em 0.9em; border-radius: 999px;
    247   font-size: calc(var(--u) * 2.8); white-space: nowrap; z-index: 4; box-shadow: 0 calc(var(--u) * 0.4) 0 rgba(0,0,0,0.25); }
    248 .ss-prompt:empty { display: none; }
    249 kbd { display: inline-block; background: #fff; color: #1A1A2E; border-radius: 0.3em; padding: 0 0.4em; font-family: inherit; font-size: 0.85em; font-weight: 600; box-shadow: 0 0.12em 0 #aab; }
    250 .ss-hud { position: absolute; left: 0; right: 0; top: 0; display: flex; justify-content: space-between; padding: calc(var(--u) * 1); pointer-events: none; z-index: 5; }
    251 .ss-chip { background: rgba(26,26,46,0.85); color: #fff; padding: 0.15em 0.7em; border-radius: 999px; font-size: calc(var(--u) * 2.6); }
    252 .ss-chip small { opacity: 0.6; font-size: 0.7em; margin-left: 0.4em; }
    253 .ss-day { position: absolute; top: calc(var(--u) * 1.4); left: 50%; transform: translateX(-50%); display: flex; gap: calc(var(--u) * 0.8); z-index: 5; }
    254 .ss-day span { width: calc(var(--u) * 2.2); height: calc(var(--u) * 2.2); border-radius: 50%; background: rgba(26,26,46,0.25); border: 2px solid rgba(26,26,46,0.4); }
    255 .ss-day span.on { background: var(--yellow); border-color: #c99e00; }
    256 
    257 .ss-toast { position: absolute; left: 50%; top: 14%; transform: translateX(-50%); background: #fff; color: #1A1A2E; padding: 0.4em 1.1em; border-radius: 999px;
    258   font-size: calc(var(--u) * 3.4); font-weight: 600; box-shadow: 0 calc(var(--u) * 0.6) 0 rgba(0,0,0,0.15); animation: ss-toast 2.6s both; z-index: 6; white-space: nowrap; }
    259 @keyframes ss-toast { 0% { transform: translate(-50%, -80%) scale(0.8); opacity: 0; } 12%, 85% { transform: translate(-50%, 0) scale(1); opacity: 1; } 100% { transform: translate(-50%, -60%); opacity: 0; } }
    260 .ss-fx { position: absolute; font-size: calc(var(--u) * 5); animation: ss-fx 1.4s ease-out both; pointer-events: none; z-index: 6; }
    261 @keyframes ss-fx { from { transform: translateY(0) scale(0.6); opacity: 1; } to { transform: translateY(-140%) scale(1.3); opacity: 0; } }
    262 
    263 /* ── Overlay panels ──────────────────────────────────────────────────────── */
    264 .ss-overlay[hidden] { display: none; }
    265 .ss-overlay { position: absolute; inset: 0; background: rgba(26,26,46,0.55); display: flex; align-items: center; justify-content: center; z-index: 20; padding: calc(var(--u) * 2); }
    266 .ss-panel { background: #fffdf5; border-radius: calc(var(--u) * 2.5); padding: calc(var(--u) * 3) calc(var(--u) * 4); max-width: 92%; max-height: 92%; overflow: auto; text-align: center;
    267   box-shadow: 0 calc(var(--u) * 1.2) 0 rgba(0,0,0,0.2); animation: ss-popin 0.3s cubic-bezier(.3,1.3,.5,1) both; }
    268 @keyframes ss-popin { from { transform: scale(0.85); } to { transform: none; } }
    269 .ss-panel h2 { font-size: calc(var(--u) * 4.4); color: var(--red); margin-bottom: calc(var(--u) * 1.6); }
    270 .ss-panel p { font-size: calc(var(--u) * 2.8); color: #555; margin-top: calc(var(--u) * 1.4); }
    271 .ss-panel p .ss-img { font-size: calc(var(--u) * 6); }
    272 .ss-list { display: flex; flex-direction: column; gap: calc(var(--u) * 1); }
    273 .ss-item { font-size: calc(var(--u) * 3.6); padding: 0.3em 1em; border-radius: 999px; border: calc(var(--u) * 0.4) solid transparent; display: flex; align-items: center; gap: 0.4em; justify-content: center; }
    274 .ss-item small { opacity: 0.5; font-size: 0.6em; }
    275 .ss-item.sel { border-color: var(--blue); background: #e8f1ff; }
    276 .ss-avatars { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 1.2); justify-content: center; font-size: calc(var(--u) * 8); max-width: calc(var(--u) * 70); }
    277 .ss-avatars .ss-img { border-radius: 25%; padding: 0.06em; border: calc(var(--u) * 0.5) solid transparent; }
    278 .ss-avatars .ss-img.sel { border-color: var(--blue); background: #e8f1ff; transform: scale(1.12); }
    279 .ss-namefield { font-size: calc(var(--u) * 5); min-height: 1.4em; min-width: 6em; border-bottom: calc(var(--u) * 0.5) solid var(--blue); display: inline-block; padding: 0 0.4em; margin-top: calc(var(--u) * 1); }
    280 .ss-namefield::after { content: '|'; animation: ss-blink 1s steps(2) infinite; color: var(--blue); }
    281 @keyframes ss-blink { 50% { opacity: 0; } }
    282 .ss-big-letter { font-size: calc(var(--u) * 16); font-weight: 600; color: var(--blue); line-height: 1.1; animation: ss-bounce 1.2s ease-in-out infinite; }
    283 .ss-books { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 1.2); justify-content: center; max-width: calc(var(--u) * 80); align-items: flex-end; }
    284 .ss-shelf-label { width: 100%; text-align: left; font-size: calc(var(--u) * 2.6); color: #98876a; margin-top: calc(var(--u) * 1); border-bottom: 2px solid #eee3c8; }
    285 .ss-book-mini { width: calc(var(--u) * 10); padding: calc(var(--u) * 0.6); border-radius: calc(var(--u) * 1); border: calc(var(--u) * 0.4) solid transparent; font-size: calc(var(--u) * 2.4); display: flex; flex-direction: column; align-items: center; }
    286 .ss-book-mini .ss-img { font-size: calc(var(--u) * 5.5); }
    287 .ss-book-mini.shaky { opacity: 0.55; }
    288 .ss-book-mini.sel { border-color: var(--blue); background: #e8f1ff; }
    289 .ss-summary { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 1.2); justify-content: center; font-size: calc(var(--u) * 6); }
    290 .ss-day-book { display: inline-flex; flex-direction: column; align-items: center; font-size: calc(var(--u) * 6); }
    291 .ss-day-book i { font-style: normal; font-size: calc(var(--u) * 2.2); color: #555; }
    292 
    293 /* ── Phone portrait ──────────────────────────────────────────────────────── */
    294 .ss-root.ss-narrow .ss-shelf { width: calc(var(--u) * 14); }
    295 .ss-root.ss-narrow .ss-window { width: calc(var(--u) * 46); }
    296 .ss-root.ss-narrow .ss-queue { left: 2%; bottom: 30%; gap: calc(var(--u) * 1.2); }
    297 .ss-root.ss-narrow .ss-patron { width: calc(var(--u) * 13); }
    298 .ss-root.ss-narrow .ss-customer { right: 2%; bottom: 30%; }
    299 .ss-root.ss-narrow .ss-desk { left: 50%; width: calc(var(--u) * 84); height: calc(var(--u) * 22); }
    300 .ss-root.ss-narrow .ss-stamp { right: 2%; }
    301 .ss-root.ss-narrow .ss-prompt { bottom: 2%; font-size: calc(var(--u) * 2.5); }
    302 .ss-root.ss-narrow .ss-box { width: calc(var(--u) * 6.5); height: calc(var(--u) * 7.5); font-size: calc(var(--u) * 4.6); }
    303 .ss-root.ss-narrow .ss-box.wide { width: calc(var(--u) * 10); }
    304 
    305 /* ── Test mode: no waiting on animations ─────────────────────────────────── */
    306 .ss-root.ss-test, .ss-root.ss-test * { animation-duration: 0.01s !important; animation-delay: 0s !important; transition-duration: 0.01s !important; }