/* Tapp The Button - the roomy cartoon pass (Nov 2026).
   Loaded last. The widget was a 325x512 card on every screen, so on a laptop it
   sat in the middle of a teal field with everything pressed together. On the
   standalone page it now takes the room it is given; inside the hero embed it
   keeps its size and only gains the cartoon line.

   The line: one ink (#2c2416), thick outlines, a hard 0 4px shadow under
   anything you can press, wood and paper for anything that is a sign. The art
   in assets/ui/ is drawn in the same line. Tapp's own face and the mascot logo
   are the owner's drawings and are not touched here. */

:root {
  --ink: #2c2416;
  --paper: #fff8ea;
  --wood: #c98a4b;
  --wood-dark: #8a5428;
  --pop: 0 4px 0 var(--ink);
  --pop-sm: 0 3px 0 var(--ink);
}

/* ------------------------------------------------------------ the frame */
html:not(.embed) body { padding: 0; }
html:not(.embed) {
  --widget-w: min(600px, 100vw);
  --widget-h: min(920px, calc(100svh - 32px));
}
html:not(.embed) #app {
  border: 4px solid var(--ink);
  border-radius: 28px;
  box-shadow: 0 8px 0 var(--ink), 0 30px 80px rgba(12, 40, 52, .45);
}
@media (max-width: 640px) {
  html:not(.embed) { --widget-w: 100vw; --widget-h: 100svh; }
  html:not(.embed) #app { border: 0; border-radius: 0; box-shadow: none; }
}

/* ---------------------------------------------------------------- HUD */
.icon-btn {
  border: 3px solid var(--ink) !important;
  border-radius: 14px !important;
  background: var(--paper) !important;
  box-shadow: var(--pop-sm) !important;
}
.icon-btn:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink) !important; }
.chip {
  border: 3px solid var(--ink) !important;
  background: var(--paper) !important;
  box-shadow: var(--pop-sm) !important;
}
.chip b { font-family: var(--shout); font-weight: 400; letter-spacing: .02em; }
.brand { border: 3px solid var(--ink) !important; box-shadow: var(--pop-sm) !important; }
.adslot {
  border: 3px solid var(--ink) !important;
  border-radius: 16px !important;
  box-shadow: var(--pop-sm) !important;
}

/* The two modes are one switch: a paper track with a coloured knob. */
.modes {
  gap: 0 !important;
  padding: 4px;
  border: 3px solid var(--ink);
  border-radius: 18px;
  background: rgba(255, 248, 234, .78);
  box-shadow: var(--pop-sm);
}
.mode-btn {
  border: 0 !important;
  border-radius: 13px !important;
  background: transparent !important;
  box-shadow: none !important;
  justify-content: center;
  transition: background .2s ease, transform .15s ease;
}
.mode-btn.is-on {
  background: #ffd34d !important;
  box-shadow: inset 0 0 0 2.5px var(--ink), 0 2px 0 var(--ink) !important;
}
.mode-copy b { font-family: var(--shout) !important; font-weight: 400; letter-spacing: .03em !important; text-transform: none !important; }
.mode-btn.is-ready::after { margin-left: 4px !important; }

/* ------------------------------------------------------------- the field */
/* The meadow's front edge: tufts and flowers between the field and the bar. */
.stage { position: relative; }
.stage::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: clamp(44px, 9vh, 80px);
  background: url('../assets/ui/meadow-front.svg') center bottom / auto 100% repeat-x;
  pointer-events: none;
  z-index: 0;
}
.tapp-console, .giveaway-bar, .status-strip { position: relative; z-index: 1; }

/* Props: the drawings are the buttons, each standing on its own shadow. */
.side-btn { background: transparent !important; box-shadow: none !important; padding: 0 !important; gap: 4px !important; }
.side-btn .prop-art { display: block; width: clamp(62px, 13vh, 104px); height: auto; filter: none; transition: transform .2s cubic-bezier(.3, 1.6, .5, 1); }
.side-btn:hover .prop-art { transform: translateY(-4px) rotate(-3deg); }
.side-btn:active .prop-art { transform: translateY(2px) scale(.96); }
.shop-btn .prop-art { width: clamp(52px, 11vh, 88px); }

/* Signs are planks. */
.side-btn .label, .crawl-door .label {
  min-width: 70%;
  padding: 3px 10px 4px !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: url('../assets/ui/plank.svg') center / 100% 100% no-repeat !important;
  color: #fff8ea !important;
  font-family: var(--shout) !important;
  font-size: clamp(.62rem, 1.7vh, .86rem) !important;
  letter-spacing: .04em !important;
  text-transform: uppercase;
  text-shadow: 0 2px 0 var(--wood-dark), 1px 0 0 var(--wood-dark), -1px 0 0 var(--wood-dark) !important;
  box-shadow: none !important;
}

/* Tapp stands on a grassy mound. */
.tapp-wrap::before { display: none !important; }
.tapp-mound {
  position: absolute;
  left: 50%;
  top: 70%;
  width: 178%;
  aspect-ratio: 320 / 120;
  transform: translateX(-50%);
  background: url('../assets/ui/pedestal.svg') center / contain no-repeat;
  z-index: -1;
  pointer-events: none;
}
.tapp-label {
  font-family: var(--shout) !important;
  color: #fff8ea !important;
  -webkit-text-stroke: 0;
  text-shadow: 0 3px 0 var(--ink), 2px 0 0 var(--ink), -2px 0 0 var(--ink), 0 -2px 0 var(--ink) !important;
  letter-spacing: .06em !important;
  position: relative;
  z-index: 2;
}
.tap-hint {
  border: 2.5px solid var(--ink) !important;
  background: var(--paper) !important;
  color: var(--ink) !important;
  box-shadow: var(--pop-sm) !important;
  position: relative;
  z-index: 2;
}

/* The way down: the arch is the button, its sign is a plank. */
.crawl-door .prop-art { width: clamp(40px, 8vh, 70px); height: auto; display: block; }
.crawl-door .flame { transform-origin: 50% 100%; }
.crawl-door:hover .prop-art { transform: translateY(-3px); }

/* The floor bars are boards: wood rim, paper inside. */
.giveaway-bar, .status-strip {
  border: 4px solid var(--wood) !important;
  border-radius: 18px !important;
  background: var(--paper) !important;
  box-shadow: 0 0 0 3px var(--ink), 0 6px 0 3px var(--ink) !important;
  margin-left: 8px !important;
  margin-right: 8px !important;
}
.strip-track { border: 2px solid var(--ink); border-radius: 99px !important; background: #f1e4c8 !important; height: 10px !important; }
.strip-track i { border-radius: 99px; background: linear-gradient(90deg, #ffd34d, #ff9d3d) !important; }
.mini-btn {
  border: 2.5px solid var(--ink) !important;
  background: #ffd34d !important;
  box-shadow: var(--pop-sm) !important;
  font-family: var(--shout) !important;
  font-weight: 400 !important;
}
.mini-btn:active { transform: translateY(3px); box-shadow: none !important; }
.odds { border: 2px solid var(--ink) !important; }

/* ---------------------------------------- the standalone page has room */
html:not(.embed) .topbar { padding: 12px 14px 4px !important; }
html:not(.embed) .icon-btn { width: 46px; height: 46px; }
html:not(.embed) .brand-logo { height: 54px !important; }
html:not(.embed) .chip { padding: 5px 12px 5px 6px; font-size: 1rem; }
html:not(.embed) .chip-ico { width: 24px; height: 24px; }
html:not(.embed) .adslot { margin: 8px 14px 0 !important; padding: 8px 12px !important; }
html:not(.embed) .modes { margin: 10px 14px 0 !important; }
html:not(.embed) .mode-btn { padding: 8px 10px !important; }
html:not(.embed) .mode-copy b { font-size: .86rem !important; }
html:not(.embed) .mode-copy em { font-size: .68rem !important; }
html:not(.embed) .mode-ico { width: 20px; height: 20px; }
html:not(.embed) .stage { padding: 6px 14px 14px !important; }
html:not(.embed) .tapp-console { gap: 6px 14px !important; }
html:not(.embed) #tapp-btn {
  --tapp-size: clamp(140px, min(30vh, 50vw), 240px);
  width: var(--tapp-size) !important;
  height: var(--tapp-size) !important;
}
html:not(.embed) .tapp-label { font-size: clamp(1rem, 2.6vh, 1.4rem) !important; margin-top: 18px; }
html:not(.embed) .tap-hint { font-size: clamp(.62rem, 1.5vh, .8rem) !important; padding: 5px 12px !important; margin-top: 8px; }
html:not(.embed) .crawl-door { right: 18px !important; top: 10px !important; }
html:not(.embed) .giveaway-bar, html:not(.embed) .status-strip { padding: 10px 14px 12px !important; margin-top: 14px !important; margin-bottom: 6px !important; }
html:not(.embed) .strip-metric b, html:not(.embed) .gb-state b { font-size: .95rem !important; }
html:not(.embed) .strip-metric em, html:not(.embed) .gb-state em { font-size: .74rem !important; }
html:not(.embed) .strip-goal-label { font-size: .8rem !important; }
html:not(.embed) .mini-btn { font-size: .8rem !important; padding: 5px 12px !important; }
html:not(.embed) .odds { font-size: .7rem !important; padding: 4px 9px !important; }

/* ------------------------------------------------ the hero embed is tight */
/* 325x340: keep every control, drop the second lines that only explain. */
html.embed .mode-copy em { display: none !important; }
html.embed .modes { margin: 4px 7px 0 !important; padding: 3px; border-width: 2.5px; }
html.embed .mode-btn { padding: 3px 6px !important; }
html.embed .mode-copy b { font-size: .62rem !important; }
html.embed .side-btn .prop-art { width: 50px; }
html.embed .shop-btn .prop-art { width: 42px; }
html.embed .side-btn .label { font-size: .5rem !important; padding: 2px 7px 3px !important; }
html.embed .crawl-door .prop-art { width: 30px; }
html.embed .crawl-door .label { font-size: .4rem !important; padding: 1px 5px 2px !important; }
html.embed .stage::after { height: 34px; }
html.embed .giveaway-bar, html.embed .status-strip { margin: 4px 6px 7px !important; border-width: 3px !important; box-shadow: 0 0 0 2.5px var(--ink), 0 4px 0 2.5px var(--ink) !important; }
html.embed .icon-btn, html.embed .chip, html.embed .brand { border-width: 2.5px !important; }

/* ------------------------------------------------------------ 3D Tapp */
/* tapp3d.js draws the ball, the bots and the machines on a canvas centred on
   the button. The button underneath keeps the click; the flat face only hides
   once the canvas has drawn its first frame (html.tapp3d-on). */
.tapp3d {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -52%);
  pointer-events: none;
  z-index: 2;
}
.tapp3d canvas { display: block; width: 100% !important; height: 100% !important; }
html.tapp3d-on .tapp-face,
html.tapp3d-on .tapp-glow { opacity: 0; }
html.tapp3d-on #tapp-btn.pressed .tapp-face,
html.tapp3d-on #tapp-btn:active .tapp-face { transform: none; }
html.tapp3d-on .tapp-art { z-index: 3; }
html.tapp3d-on .tap-float,
html.tapp3d-on .combo-badge { z-index: 7; }
html.tapp3d-on #tapp-btn:focus-visible { outline: 3px solid #ffd34d; outline-offset: 6px; }

/* ------------------------------------------------------------ Tapp, drawn */
/* Tapp is the owner's drawing (assets/tapp_mascotte.png), cut into four layers
   by the asset script - the disc, each hand, the two marks - and nothing redrawn.
   The layers move on their own: he bobs, waves, grips the edge, and squashes
   when he is pressed. Positions come from the cut, so the rig lines up with the
   drawing to the pixel. The 3D canvas still carries the bots, the machines and
   the coins; the ball in it is only an invisible blocker so a bot walking
   behind Tapp is hidden by him. */
.tapp-rig {
  position: absolute;
  left: -26.750%;
  top: -17.948%;
  width: 142.765%;
  height: 127.952%;
  pointer-events: none;
  z-index: 1;
  transform-origin: 53.76% 92.18%;
  animation: rig-bob 2.8s ease-in-out infinite;
}
.tapp-rig > * { position: absolute; display: block; max-width: none; user-select: none; -webkit-user-drag: none; }
.rig-disc { left:18.271%;top:14.597%;width:72.406%;height:76.594%; transform-origin: 50% 92%; z-index: 2; }
.rig-tint { left:18.271%;top:14.597%;width:72.406%;height:76.594%; z-index: 3; opacity: 0; transition: opacity .3s ease; -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }
.rig-tint-ring { -webkit-mask-image: url(../assets/rig/tapp-ring-mask.png); mask-image: url(../assets/rig/tapp-ring-mask.png); background: var(--tapp-rim, #2a2a2a); mix-blend-mode: color; }
.rig-tint-face { -webkit-mask-image: url(../assets/rig/tapp-face-mask.png); mask-image: url(../assets/rig/tapp-face-mask.png); background: var(--tapp-body, #fff); mix-blend-mode: multiply; }
.rig-hand-r { left:76.617%;top:18.708%;width:23.383%;height:34.228%; transform-origin: 35.99% 46.59%; z-index: 4; animation: rig-wave 3.6s ease-in-out infinite; }
.rig-hand-l { left:0.000%;top:76.258%;width:28.571%;height:23.742%; transform-origin: 83.21% 16.50%; z-index: 4; animation: rig-grip 2.8s ease-in-out infinite; }
.rig-marks { left:5.113%;top:0.000%;width:24.436%;height:37.919%; transform-origin: 90% 100%; z-index: 1; animation: rig-marks 1.9s ease-in-out infinite; }

/* a worn skin tints the bezel and the face; Classic is the drawing as drawn */
#tapp-btn:not([data-skin="skin-classic"]) .rig-tint-ring { opacity: .85; }
#tapp-btn:not([data-skin="skin-classic"]) .rig-tint-face { opacity: .55; }

@keyframes rig-bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-2.2%) rotate(-1.2deg); }
}
@keyframes rig-wave {
  0%, 52%, 100% { transform: rotate(0deg); }
  60% { transform: rotate(-16deg); }
  68% { transform: rotate(8deg); }
  76% { transform: rotate(-14deg); }
  84% { transform: rotate(4deg); }
}
@keyframes rig-grip {
  0%, 100% { transform: rotate(0deg) translateY(0); }
  50% { transform: rotate(-5deg) translateY(-2%); }
}
@keyframes rig-marks {
  0%, 100% { transform: rotate(0deg) scale(1); }
  40% { transform: rotate(-7deg) scale(1.06); }
  55% { transform: rotate(3deg) scale(.98); }
}

/* the press: squash, a jolt in both hands, the marks shout */
.tapp-rig.is-hit .rig-disc { animation: rig-squash .38s cubic-bezier(.3, 1.6, .5, 1); }
.tapp-rig.is-hit .rig-hand-r { animation: rig-jolt-r .38s ease-out; }
.tapp-rig.is-hit .rig-hand-l { animation: rig-jolt-l .38s ease-out; }
.tapp-rig.is-hit .rig-marks { animation: rig-shout .45s cubic-bezier(.3, 1.8, .5, 1); }
@keyframes rig-squash {
  0% { transform: scale(1, 1); }
  25% { transform: scale(1.09, .88); }
  55% { transform: scale(.96, 1.05); }
  100% { transform: scale(1, 1); }
}
@keyframes rig-jolt-r { 30% { transform: rotate(-22deg) translateY(4%); } }
@keyframes rig-jolt-l { 30% { transform: rotate(12deg) translateY(6%); } }
@keyframes rig-shout { 35% { transform: scale(1.3) rotate(-10deg); } }
/* a ticket in: a little hop and a full wave */
.tapp-rig.is-happy { animation: rig-hop .7s cubic-bezier(.3, 1.4, .5, 1); }
.tapp-rig.is-happy .rig-hand-r { animation: rig-wave .9s ease-in-out 2; }
@keyframes rig-hop { 40% { transform: translateY(-12%) rotate(-4deg); } 70% { transform: translateY(1%) scale(1.04, .96); } }

/* the drawn rig replaces the flat face and the old 3D ball */
html.tapp-rig-on .tapp-face,
html.tapp-rig-on .tapp-glow { opacity: 0; }
html.tapp-rig-on #tapp-btn.pressed .tapp-face,
html.tapp-rig-on #tapp-btn:active .tapp-face { transform: none; }
html.tapp-rig-on .tapp3d { z-index: 5; }
html.tapp-rig-on .tapp-art { z-index: 6; }

@media (prefers-reduced-motion: reduce) {
  .tapp-rig, .tapp-rig > * { animation: none !important; }
}

/* ------------------------------------------- the floor lives in the shop */
/* The factory used to be a door of its own standing next to the shop, and two
   doors for one decision is a lot of why the console read as two games. The
   lanes now sit at the top of the Machines shelf: what is working, what it
   pays, and the next machine to buy are one screen. */
.floor-inline {
  margin: 6px 0 12px;
  padding: 10px 12px 12px;
  border: 3px solid var(--ink);
  border-radius: 16px;
  background: #fdf3dd;
  box-shadow: 0 3px 0 var(--ink);
}
.floor-inline-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.floor-inline-head .panel-h3 { margin: 0; }
.floor-inline .floor-empty { margin: 4px 2px 10px; }
.floor-inline .floor-lanes { display: grid; gap: 10px; }

/* ------------------------------------------------------------ reading size */
/* Nearly all of this widget is sized in rem on a 16px root, and the small type
   sat between .44 and .58rem: seven pixel signs with an ink shadow on them,
   nine and ten pixel shop leads. That is what "the text gets mushed" is - it
   was never a colour problem. The standalone page has the room, so it gets a
   bigger root and a floor under its smallest type. The 325px embed keeps the
   old scale, because it genuinely has no room. */
/* The root was 14px (game.css sets it on :root), so every rem in the widget
   rendered 12% smaller than it was written: .48rem came out at 6.7px. It goes
   back to the browser's own 16px here, which lifts every rem-based size at once
   without touching a single rule. Going further - 20px - scaled the chips and
   the bars with the words and the header collided with itself, so 16 is where
   it stops. */
html:not(.embed) { font-size: 16px; }

html:not(.embed) .tap-hint,
html:not(.embed) .side-btn .label,
html:not(.embed) .crawl-door .label,
html:not(.embed) .adslot-copy b,
html:not(.embed) .adslot-copy em,
html:not(.embed) .adslot-cta,
html:not(.embed) .odds,
html:not(.embed) .mini-btn,
html:not(.embed) .daily-copy em,
html:not(.embed) .daily-btn em,
html:not(.embed) .gb-state em,
html:not(.embed) .gb-clock-text,
html:not(.embed) .strip-metric em,
html:not(.embed) .strip-goal-label,
html:not(.embed) .shop-tab,
html:not(.embed) .panel-lead,
html:not(.embed) .panel-tip,
html:not(.embed) .floor-empty,
html:not(.embed) .chest-lead,
html:not(.embed) .pin-name,
html:not(.embed) .pin-when {
  font-size: .8rem !important;
}

/* A heading is a heading at any width, and body copy is read at 15px. */
html:not(.embed) .panel-h3 { font-size: 1.05rem !important; }
html:not(.embed) .shop-tab { font-size: .85rem !important; }
html:not(.embed) .panel-lead,
html:not(.embed) .panel-tip,
html:not(.embed) .floor-empty,
html:not(.embed) .chest-lead { font-size: .94rem !important; line-height: 1.55; }

/* The shop and floor lanes carry the smallest print in the game, so they get the
   most room: two words on a line is a wall, and one line is a label. */
html:not(.embed) .upgrade-line,
html:not(.embed) .upgrade-note,
html:not(.embed) .contract-line,
html:not(.embed) .floor-row-sub { font-size: .76rem !important; line-height: 1.45; }

/* The lane's own plank sign: the machine name and what it pays. It was set at
   .62rem and rode off the end of a plank that is drawn at a fixed width. */
html:not(.embed) .lane-tag b { font-size: .9rem !important; }
html:not(.embed) .lane-tag span { font-size: .7rem !important; }
html:not(.embed) .floor-total { font-size: .8rem !important; }
html:not(.embed) .lane-more { font-size: .68rem !important; }

/* ------------------------------------------------------ the last small type */
/* What was still under eleven pixels: the strip's units and its price, the pin
   states in the chest, and the shop rows - a machine's name, its level, and the
   line that says what it pays. Those are written with #app further up, so this
   block carries #app too and comes last. */
html:not(.embed) #app .strip-metric em,
html:not(.embed) #app .strip-cost b,
html:not(.embed) #app .strip-goal-label,
html:not(.embed) #app .gb-clock-text,
html:not(.embed) #app .pin-when,
html:not(.embed) #app .pin-shelf span,
html:not(.embed) #app .pin-week span,
html:not(.embed) #app .upgrade-copy .level,
html:not(.embed) #app .buy-btn { font-size: .78rem !important; }
html:not(.embed) #app .upgrade-copy .name { font-size: .9rem !important; line-height: 1.3; }
html:not(.embed) #app .upgrade-copy .desc,
html:not(.embed) #app .upgrade-copy .blurb,
html:not(.embed) #app .contract-line { font-size: .8rem !important; line-height: 1.4; }

/* ------------------------------------------------------------ quiet type */
/* Titan One was doing every label, number, heading and price in the widget,
   and Silkscreen was aliased to it inside #app. Titan One is a fat rounded
   display face with one weight: a price, a heading and a footnote all shout
   exactly as loud, so the page reads as noise rather than as hierarchy. On the
   standalone page the functional text is the UI face now, in two weights, and
   Titan One survives only in the place it is drawn by hand: the TAPP word. */
html:not(.embed) #app { --shout: var(--ui); --pixel: var(--ui); }
html:not(.embed) #app .tapp-label {
  font-family: 'Titan One', var(--ui) !important;
  font-weight: 400 !important;
  letter-spacing: .04em !important;
}
/* Two weights, not five: 600 for a name or a number, 400 for a sentence. */
html:not(.embed) #app b,
html:not(.embed) #app strong,
html:not(.embed) #app .name,
html:not(.embed) #app .panel-h3,
html:not(.embed) #app .panel-head h2 { font-weight: 600 !important; }
html:not(.embed) #app em,
html:not(.embed) #app .panel-lead,
html:not(.embed) #app .panel-tip,
html:not(.embed) #app .floor-empty,
html:not(.embed) #app .chest-lead,
html:not(.embed) #app .desc,
html:not(.embed) #app .blurb,
html:not(.embed) #app .level { font-weight: 400 !important; font-style: normal !important; }
/* Shouting caps, tracking and an ink outline on both sides are what turned a
   13px label into a smudge. None of them earn their place at this size. */
html:not(.embed) #app .tap-hint,
html:not(.embed) #app .side-btn .label,
html:not(.embed) #app .crawl-door .label,
html:not(.embed) #app .lane-tag b,
html:not(.embed) #app .lane-tag span,
html:not(.embed) #app .odds,
html:not(.embed) #app .mini-btn,
html:not(.embed) #app .chip,
html:not(.embed) #app .adslot-cta,
html:not(.embed) #app .shop-tab,
html:not(.embed) #app .floor-total,
html:not(.embed) #app .lane-more,
html:not(.embed) #app .buy-btn,
html:not(.embed) #app .mode-copy b,
html:not(.embed) #app .gb-state b {
  text-transform: none !important;
  letter-spacing: 0 !important;
  text-shadow: none !important;
  -webkit-text-stroke: 0 !important;
}
/* Cream on a dark plank needs no shadow to be read. */
html:not(.embed) #app .side-btn .label,
html:not(.embed) #app .crawl-door .label,
html:not(.embed) #app .lane-tag b,
html:not(.embed) #app .lane-tag span { color: #fdf6e6 !important; }
