/* =========================================================================================
   Stretcher: "Frizzy G", the brand look (23 Oct 2026), hand-made again in the original Frizzy G
   language, the same as frizzy-g.com's and Mbao's: grey #808080, lime #55FF00, black, and white
   only for small highlights. Everything that matters is a sticker, cut out with a 3px black
   outline and slapped down on a hard black offset shadow; the big lettering is the logo's own
   lime with a fat black outline and a hard black shadow. One language, nothing borrowed from
   Night: no glass, no blur, no glows, no soft shadows, no gradients but the halftone and the odd
   small sheen.

   The palette, and what it forces:
     - the ground is mid-grey #808080; black text on it is 5.3:1, so black is the only colour
       text takes on the greys, and nothing behind text is ever darker than the ground (the dot
       screen and its swells only ever lighten it);
     - lime on grey is only 3:1, so lime is a fill (black on it, 15:1), or sits on black, or is
       lettering with the logo's black outline: never plain lime text on grey;
     - on black, text is lime or light grey (both over 10:1).

   Made for stretching: legible from a metre away and calm while you hold. On the play screen
   nothing loops and nothing sits behind the countdown: the numerals stand on the plain dot
   screen (the swells and the effects script's live halftone go away for a session), and the
   phases change colour, never move. Stickers slap down as they arrive (overshoot, then sit) and
   a hover lifts one off its shadow; under prefers-reduced-motion nothing moves at all, and the
   page still looks finished.

   Hand-written, phone first at 390px, system fonts only (the CSP allows no web fonts); icons are
   data: SVGs used as masks (the CSP allows data:). The app redraws the play screen ten times a
   second, so nothing here depends on classes it doesn't set itself. The look's script
   (frizzy.js) prints a live halftone a finger stirs lime ink into on Home and at the finish, and
   fires confetti at the end; it only adds the ffx- classes at the end of this file, and
   everything above them is the whole look without it.

   The burger, its panel and the PIN form (.look-menu, .look-burger, .look-panel, .lm-opt,
   .lm-castle, .lm-pin, .lm-pin-label, .lm-pin-row, .lm-pin-input, .lm-pin-go, .lm-pin-wrong) are
   lookmenu.css's, already stickers for Frizzy G; this sheet sizes the settings button to match.
   ========================================================================================= */

:root {
  color-scheme: light;

  /* the greys: the ground, and the steps up from it (all lighter, so black text only gains) */
  --grey: #808080;            /* the ground: black on it 5.3:1 */
  --dot: #8a8a8a;             /* the dot screen printed on the ground */
  --dot-2: #969696;           /* the halftone swells */
  --grey-2: #9b9b9b;          /* raised: cards, tracks, round buttons (black on it 7.6:1) */
  --grey-3: #b4b4b4;          /* lighter: notes, hovers, pale numerals (black on it 10:1) */
  --lime: #55ff00;
  --ink: #000000;
  --paper: #ffffff;           /* small highlights only */

  /* the sticker language */
  --line: 3px;                /* every outline */
  --sh: 5px 5px 0 var(--ink); /* the hard shadow */
  --sh-s: 3px 3px 0 var(--ink);
  --sh-l: 7px 7px 0 var(--ink);
  --r-l: 22px;
  --r-m: 14px;
  --gutter: 16px;
  --focus: var(--ink);        /* the focus ring: black on grey and lime */

  --font: "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Roboto, Arial, sans-serif;

  --ease: cubic-bezier(.2, .8, .2, 1);
  --spring: cubic-bezier(.34, 1.45, .64, 1);
  --slap: cubic-bezier(.25, 1.6, .45, 1);   /* a sticker slapped down: overshoots, then sits */

  /* the dot screen: a 45-degree lattice, 9.9px apart (two square grids, one offset half a tile),
     the same as frizzy-g.com's and Mbao's; frizzy.js prints its live halftone on exactly this
     lattice. Each dot is one radial gradient, used on both grids */
  --screen: 14px 14px;
  --d-ground: radial-gradient(circle, var(--dot) 1.15px, rgba(138, 138, 138, 0) 1.75px);
  --d-swell-1: radial-gradient(circle, var(--dot-2) 2.1px, rgba(150, 150, 150, 0) 2.7px);
  --d-swell-2: radial-gradient(circle, var(--dot-2) 3.1px, rgba(150, 150, 150, 0) 3.7px);
  /* lime ink on the grey stickers, in three sizes (the biggest never touch: 9.9px apart) */
  --d-lime-1: radial-gradient(circle, var(--lime) 0 1.3px, rgba(85, 255, 0, 0) 1.8px);
  --d-lime-2: radial-gradient(circle, var(--lime) 0 2.5px, rgba(85, 255, 0, 0) 3px);
  --d-lime-3: radial-gradient(circle, var(--lime) 0 3.6px, rgba(85, 255, 0, 0) 4.1px);
  /* and a print of darker lime on the lime ones (still far lighter than the ground) */
  --d-press: radial-gradient(circle, rgba(0, 0, 0, .15) 0 2.4px, rgba(0, 0, 0, 0) 2.9px);

  /* icons, drawn in black and used as masks so they take the text colour; chunky, to sit with
     3px outlines */
  --i-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.6l3.1 3.1 6.8-7.5' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-cross: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.9 3.9l8.2 8.2M12.1 3.9l-8.2 8.2' fill='none' stroke='%23000' stroke-width='2.9' stroke-linecap='round'/%3E%3C/svg%3E");
  --i-gear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000'%3E%3Ccircle cx='12' cy='12' r='5' stroke-width='3.8'/%3E%3Ccircle cx='12' cy='12' r='8.3' stroke-width='3.6' stroke-dasharray='3.26 3.26' transform='rotate(-11.25 12 12)'/%3E%3C/g%3E%3C/svg%3E");
  --i-restart: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5.6 15.6a7.4 7.4 0 1 0 .9-8.4L4.2 9.4'/%3E%3Cpath d='M4 4.6v5h5'/%3E%3C/g%3E%3C/svg%3E");
  --i-prev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.4 6.2v11.6l-9-5.8z' stroke='%23000' stroke-width='2.4' stroke-linejoin='round'/%3E%3Crect x='4.8' y='5.2' width='3.4' height='13.6' rx='1.5'/%3E%3C/svg%3E");
  --i-next: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.6 6.2v11.6l9-5.8z' stroke='%23000' stroke-width='2.4' stroke-linejoin='round'/%3E%3Crect x='15.8' y='5.2' width='3.4' height='13.6' rx='1.5'/%3E%3C/svg%3E");
  --i-pause: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='5.6' y='4.6' width='4.8' height='14.8' rx='1.6'/%3E%3Crect x='13.6' y='4.6' width='4.8' height='14.8' rx='1.6'/%3E%3C/svg%3E");
  --i-play: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M8 5.4v13.2l10.6-6.6z' stroke='%23000' stroke-width='2.6' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 2.5v10M3.6 8.4 8 12.8l4.4-4.4' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 13.5v-10M3.6 7.6 8 3.2l4.4 4.4' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-last: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.1 9.6A5.2 5.2 0 1 0 4.4 4'/%3E%3Cpath d='M2.6 1.9v3.2h3.2'/%3E%3Cpath d='M8.3 5.3V8.4l2 1.3'/%3E%3C/g%3E%3C/svg%3E");
  --i-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2.6 8h9.6M8.4 3.6 12.8 8l-4.4 4.4' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* lime artwork for the black discs and tiles (a mask can't take two colours) */
  --i-play-lime: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 4.6v14.8l12-7.4z' fill='%2355ff00' stroke='%2355ff00' stroke-width='2.2' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-check-lime: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.6l3.1 3.1 6.8-7.5' fill='none' stroke='%2355ff00' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* a real spring where the browser can do one */
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring: linear(0, .12 4%, .44 10%, .79 17%, .98 23%, 1.05 28%, 1.06 32%, 1.04 38%, 1.01 46%, .995 56%, 1);
    --slap: linear(0, .3 6%, .8 13%, 1.08 19%, 1.12 24%, 1.06 32%, .985 42%, .995 56%, 1);
  }
}

/* ---------- base (the screens' mechanics are the app's own: two fixed full-height screens) ---------- */

* { margin: 0; padding: 0; box-sizing: border-box; }
*::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; }
html {
  background: var(--grey);
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
}
body {
  color: var(--ink);
  font: 400 16px/1.45 var(--font);
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
input, select { user-select: text; -webkit-user-select: text; }
::selection { background: var(--lime); color: var(--ink); }

/* the ground: grey, printed with the dot screen, and two halftone swells where the screen's dots
   grow (top left, behind the name and the question; bottom right). Each swell is two rings of
   bigger, paler dots on the same lattice, nested: the outer ring's dots, wiped back to the plain
   ground beyond its reach, then the inner ring's, wiped back sooner (the plain dots ride on top
   of it all). Lighter than the grey, never darker. Static: nothing here costs a frame */
body::before {
  --a: circle at 0 0;          /* where the swell is */
  --r: min(92vw, 520px);       /* and how far it reaches */
  content: ""; position: fixed; inset: 0; z-index: -3; pointer-events: none;
  background:
    var(--d-ground) 0 0 / var(--screen), var(--d-ground) 7px 7px / var(--screen),
    radial-gradient(var(--a), rgba(128, 128, 128, 0) calc(var(--r) * .62), var(--grey) var(--r)),
    var(--d-swell-1) 0 0 / var(--screen), var(--d-swell-1) 7px 7px / var(--screen),
    radial-gradient(var(--a), rgba(128, 128, 128, 0) calc(var(--r) * .3), var(--grey) calc(var(--r) * .56)),
    var(--d-swell-2) 0 0 / var(--screen), var(--d-swell-2) 7px 7px / var(--screen),
    var(--grey);
}
/* the second swell, bottom right: the same, on a layer that's see-through beyond its reach */
body::after {
  --a: circle at 100% 100%;
  --r: min(80vw, 460px);
  content: ""; position: fixed; inset: 0; z-index: -3; pointer-events: none;
  background:
    var(--d-ground) 0 0 / var(--screen), var(--d-ground) 7px 7px / var(--screen),
    radial-gradient(var(--a), rgba(128, 128, 128, 0) calc(var(--r) * .62), var(--grey) var(--r)),
    var(--d-swell-1) 0 0 / var(--screen), var(--d-swell-1) 7px 7px / var(--screen),
    radial-gradient(var(--a), rgba(128, 128, 128, 0) calc(var(--r) * .3), var(--grey) calc(var(--r) * .56)),
    var(--d-swell-2) 0 0 / var(--screen), var(--d-swell-2) 7px 7px / var(--screen),
    var(--grey);
  -webkit-mask: radial-gradient(var(--a), #000 var(--r), rgba(0, 0, 0, 0) calc(var(--r) + 1px));
  mask: radial-gradient(var(--a), #000 var(--r), rgba(0, 0, 0, 0) calc(var(--r) + 1px));
}
/* a desktop: the swells move out into the margins, either side of the phone-shaped column */
@media (min-width: 1000px) {
  body::before { --a: circle at 12vw 18vh; --r: 30vw; }
  body::after { --a: circle at 88vw 82vh; --r: 28vw; }
}
/* a session: the plain screen only. Nothing behind the countdown, the name or the notes */
body:has(> #play:not([hidden]))::before { background: var(--d-ground) 0 0 / var(--screen), var(--d-ground) 7px 7px / var(--screen), var(--grey); }
body:has(> #play:not([hidden]))::after { content: none; }

/* the logo's lettering: lime letters in a fat black outline with a hard black shadow under it.
   The outline isn't a text-stroke: a stroke also traces the little notches heavy italic fonts
   cut into their joins (Segoe UI Black's 5, 2, 3 and 9), and they show up as black slivers
   inside the numerals. Instead the letters are fattened a hair with a stroke of their OWN
   colour (which closes the notches), and the outline is twelve copies of them set round a
   circle under the text, the shadow eight more moved down and right. All text-shadows, so the
   same in every browser, and never a filter. Each lettered thing sets the sizes (--o the
   outline, --dx --dy the shadow, in em, so they scale with the text) and the colours (--fill,
   --edge, --drop), and the list below does the rest */
.logo-text, .time-card .t-num {
  --fill: var(--lime); --edge: var(--ink); --drop: var(--ink);
  --o: .075em; --dx: .055em; --dy: .06em; --dil: .02em;
  font-style: italic; font-weight: 900;
}
.logo-text, .time-card .t-num, .countdown .of {
  color: var(--fill);
  -webkit-text-stroke: var(--dil) var(--fill);
  text-shadow:
    var(--o) 0 0 var(--edge),
    calc(var(--o) * .866) calc(var(--o) * .5) 0 var(--edge),
    calc(var(--o) * .5) calc(var(--o) * .866) 0 var(--edge),
    0 var(--o) 0 var(--edge),
    calc(var(--o) * -.5) calc(var(--o) * .866) 0 var(--edge),
    calc(var(--o) * -.866) calc(var(--o) * .5) 0 var(--edge),
    calc(var(--o) * -1) 0 0 var(--edge),
    calc(var(--o) * -.866) calc(var(--o) * -.5) 0 var(--edge),
    calc(var(--o) * -.5) calc(var(--o) * -.866) 0 var(--edge),
    0 calc(var(--o) * -1) 0 var(--edge),
    calc(var(--o) * .5) calc(var(--o) * -.866) 0 var(--edge),
    calc(var(--o) * .866) calc(var(--o) * -.5) 0 var(--edge),
    calc(var(--dx) + var(--o) * .766) calc(var(--dy) + var(--o) * -.643) 0 var(--drop),
    calc(var(--dx) + var(--o) * .963) calc(var(--dy) + var(--o) * -.271) 0 var(--drop),
    calc(var(--dx) + var(--o) * .989) calc(var(--dy) + var(--o) * .149) 0 var(--drop),
    calc(var(--dx) + var(--o) * .84) calc(var(--dy) + var(--o) * .543) 0 var(--drop),
    calc(var(--dx) + var(--o) * .543) calc(var(--dy) + var(--o) * .84) 0 var(--drop),
    calc(var(--dx) + var(--o) * .149) calc(var(--dy) + var(--o) * .989) 0 var(--drop),
    calc(var(--dx) + var(--o) * -.271) calc(var(--dy) + var(--o) * .963) 0 var(--drop),
    calc(var(--dx) + var(--o) * -.643) calc(var(--dy) + var(--o) * .766) 0 var(--drop);
}

button {
  font: inherit; color: inherit; margin: 0; border: 0; background: none;
  appearance: none; -webkit-appearance: none;
  cursor: pointer; touch-action: manipulation; /* no double-tap-zoom delay on phones */
  -webkit-tap-highlight-color: transparent;
}
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
:focus:not(:focus-visible) { outline: none; }

/* icon buttons: the app's glyphs (emoji on some phones) give way to crisp drawn icons; the
   buttons keep their aria-labels, so nothing changes for a screen reader */
#btnSettings, #btnExit, .play-controls button { font-size: 0; color: var(--ink); }
#btnSettings::before, #btnExit::before, .play-controls button::before {
  content: ""; position: absolute; inset: 0; margin: auto; width: 22px; height: 22px;
  background: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat;
  pointer-events: none;
}
#btnSettings { --icon: var(--i-gear); }
#btnExit { --icon: var(--i-cross); }
#btnRestart { --icon: var(--i-restart); }
#btnBack { --icon: var(--i-prev); }
#btnSkip { --icon: var(--i-next); }
#btnPlayPause { --icon: var(--i-pause); }
#btnPlayPause[aria-label="Resume"] { --icon: var(--i-play); }
#btnPlayPause[aria-label="Finished"] { --icon: var(--i-check); }

/* the round sticker buttons in the corners, the same size and cut as the burger beside them:
   a hover lifts one off its shadow, a press stamps it down into it */
button.icon {
  position: relative; flex: none; width: 44px; height: 44px; border-radius: 50%;
  background: var(--grey-2);
  border: var(--line) solid var(--ink);
  box-shadow: 4px 4px 0 var(--ink);
  transition: transform .4s var(--spring), box-shadow .2s var(--ease), background-color .15s var(--ease);
}
button.icon::before { transition: transform .5s var(--spring); }
@media (hover: hover) {
  button.icon:hover { background-color: var(--grey-3); transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--ink); }
}
button.icon:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--ink); transition-duration: .08s; }
/* settings open: the button goes lime and stays pressed, as the burger does; the gear turns */
#btnSettings[aria-expanded="true"] { background: var(--lime); transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--ink); }
#btnSettings[aria-expanded="true"]::before { transform: rotate(60deg); }

/* ---------- screens ---------- */

/* each screen is the full dynamic viewport, capped in width so a desktop gets a phone-shaped column */
.screen {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 100vh;
  height: 100dvh;
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  padding: max(12px, env(safe-area-inset-top)) max(var(--gutter), env(safe-area-inset-right))
           max(14px, env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
}

/* ---------- home: the top bar ---------- */

.topbar { display: flex; align-items: center; gap: 10px; flex-shrink: 0; min-height: 50px; }
.top-end { margin-right: 4px; } /* room for the hard shadows */

/* the wordmark, with the logo's underline bar: a lime strip, cut out in black, on its own hard
   shadow. It stretches out once as the page arrives (it is called Stretcher) */
.brand {
  flex: 1; min-width: 0; position: relative; align-self: center;
  padding: 0 0 13px 2px; white-space: nowrap;
  font-size: 30px; line-height: 1.1; letter-spacing: .01em;
}
.brand::after {
  content: ""; position: absolute; left: 3px; bottom: 0; width: 6.1em; max-width: calc(100% - 8px); height: 10px;
  background: var(--lime); border: var(--line) solid var(--ink); border-radius: 4px;
  box-shadow: var(--sh-s);
  transform-origin: 0 50%;
  animation: ffx-stretch .9s var(--slap) .25s backwards;
}

.scroll {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch;
  /* run to the screen's edges, so the hard shadows and focus rings are never clipped */
  margin: 0 calc(-1 * var(--gutter)); padding: 0 var(--gutter);
  scrollbar-width: thin; scrollbar-color: rgba(0, 0, 0, .45) transparent;
}

/* ---------- settings: a grey sticker, like the look panel beside it ---------- */

.settings-panel {
  position: relative; flex-shrink: 0;
  display: flex; flex-direction: column;
  margin: 2px 6px 8px 0; padding: 4px 16px 14px; border-radius: var(--r-l);
  background: var(--grey-2); color: var(--ink);
  border: var(--line) solid var(--ink);
  box-shadow: var(--sh);
  font: 700 15px/1.3 var(--font);
  animation: ffx-slap .5s var(--slap) backwards;
}
/* each row ends in a line of black dots, the dot screen in ink */
.settings-panel label {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  min-height: 58px; padding: 8px 0;
  background: radial-gradient(circle, var(--ink) 1.1px, rgba(0, 0, 0, 0) 1.6px) 0 100% / 7px 4px repeat-x;
  cursor: pointer;
}
.settings-panel input[type="number"] {
  flex: none; width: 80px; min-height: 44px; margin-right: 3px; padding: 0 12px; border: 0; border-radius: var(--r-m);
  font: 800 16px/1 var(--font); color: var(--ink); text-align: center; font-variant-numeric: tabular-nums;
  background-color: var(--paper);
  box-shadow: inset 0 0 0 var(--line) var(--ink), var(--sh-s);
}
.settings-panel input[type="number"]:focus-visible { outline-offset: 2px; }
/* the two checkboxes become switches: a white knob, outlined, that slides along a grey track
   onto a lime one, so on and off differ by position as well as colour */
.settings-panel input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; flex: none;
  width: 60px; height: 36px; margin-right: 3px; border-radius: 999px; cursor: pointer;
  background: radial-gradient(circle closest-side, var(--paper) 0 62%, var(--ink) 66% 92%, rgba(0, 0, 0, 0) 96%) 0 50% / 36px 36px no-repeat, var(--grey);
  box-shadow: inset 0 0 0 var(--line) var(--ink), var(--sh-s);
  transition: background-position .4s var(--spring), background-color .15s var(--ease);
}
.settings-panel input[type="checkbox"]:checked {
  background: radial-gradient(circle closest-side, var(--paper) 0 62%, var(--ink) 66% 92%, rgba(0, 0, 0, 0) 96%) 100% 50% / 36px 36px no-repeat, var(--lime);
}
.fine-print { margin-top: 12px; font-size: 12.5px; font-weight: 600; line-height: 1.5; color: var(--ink); }
.fine-print b { font-weight: 900; }

/* ---------- home: three questions, a card at a time ---------- */

/* what's tight, how long, how long a hold. Each step is a screenful of big sticker cards (app.js
   draws them afresh, so they're slapped down again every step) and fits a 390 x 844 phone without
   scrolling. A card that starts a session (a hold, or Desk break) is lime with a play disc, like
   every other "go" in Frizzy G; the rest are grey, cut out in black, with lime ink in a corner */
#dashboard { display: flex; flex-direction: column; padding-bottom: 12px; }
#home { --s1: var(--lime); --s2: var(--grey-3); --s3: var(--grey-3); }
#home[data-step="time"] { --s2: var(--lime); }
#home[data-step="hold"] { --s2: var(--lime); --s3: var(--lime); }

.hero { display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px; padding: 4px 2px 0; flex-shrink: 0; }
.step-back {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; margin-right: 3px; padding: 0 16px 0 13px; border-radius: 999px;
  font: italic 900 14.5px/1 var(--font); letter-spacing: .01em; color: var(--ink); white-space: nowrap;
  background: var(--grey-2); border: var(--line) solid var(--ink); box-shadow: var(--sh-s);
  transition: transform .4s var(--spring), box-shadow .2s var(--ease), background-color .15s var(--ease);
  animation: ffx-pop .45s var(--slap) backwards;
}
@media (hover: hover) { .step-back:hover { background-color: var(--grey-3); transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--ink); } }
.step-back:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); transition-duration: .08s; }
.hero-kicker {
  flex: 1 1 0; display: flex; align-items: center; gap: 10px; min-width: 0; min-height: 44px;
  font: 800 12px/1.25 var(--font); letter-spacing: .15em; text-transform: uppercase; color: var(--ink);
}
/* where you are: three dots on a line, lime for each step so far (the words say it too) */
.hero-kicker::before {
  content: ""; flex: none; width: 44px; height: 13px;
  background:
    radial-gradient(circle closest-side, var(--s1) 0 50%, var(--ink) 56% 88%, rgba(0, 0, 0, 0) 95%) 0 50% / 13px 13px no-repeat,
    radial-gradient(circle closest-side, var(--s2) 0 50%, var(--ink) 56% 88%, rgba(0, 0, 0, 0) 95%) 50% 50% / 13px 13px no-repeat,
    radial-gradient(circle closest-side, var(--s3) 0 50%, var(--ink) 56% 88%, rgba(0, 0, 0, 0) 95%) 100% 50% / 13px 13px no-repeat,
    linear-gradient(var(--ink), var(--ink)) 50% 50% / 100% 3px no-repeat;
}
.hero-title {
  flex: 1 0 100%; position: relative;
  font-size: 38px; line-height: 1.04; letter-spacing: .005em;
  padding: 2px .1em .08em 0;
  text-wrap: balance;
}
/* the app moves focus here at each step so a screen reader hears the question; it isn't a control */
.hero-title:focus { outline: none; }

/* the cards */
.cards { display: grid; gap: 14px 12px; margin: 16px 6px 6px 0; flex: 1 0 auto; }
.card {
  --off: 5px; --r: var(--r-l);
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  min-width: 0; min-height: 44px; padding: 14px 15px 15px; border-radius: var(--r); text-align: left; line-height: 1.2;
  color: var(--ink); background: var(--grey-2);
  border: var(--line) solid var(--ink);
  box-shadow: var(--off) var(--off) 0 var(--ink);
  transition: transform .45s var(--spring), box-shadow .2s var(--ease);
  animation: ffx-slap .6s var(--slap) backwards;
}
.cards > :nth-child(2) { animation-delay: .04s; }
.cards > :nth-child(3) { animation-delay: .08s; }
.cards > :nth-child(4) { animation-delay: .12s; }
.cards > :nth-child(5) { animation-delay: .16s; }
.cards > :nth-child(6) { animation-delay: .2s; }
.cards > :nth-child(7) { animation-delay: .24s; }
.cards > :nth-child(8) { animation-delay: .3s; }
@media (hover: hover) {
  .card:hover { transform: translate(-2px, -2px); box-shadow: calc(var(--off) + 2px) calc(var(--off) + 2px) 0 var(--ink); }
}
.card:active { transform: translate(calc(var(--off) - 1px), calc(var(--off) - 1px)); box-shadow: 1px 1px 0 var(--ink); transition-duration: .08s; }
.card:focus-visible { outline-offset: 5px; }
.c-name { font: italic 900 18px/1.08 var(--font); letter-spacing: -.01em; }
.c-note { font: 600 13px/1.3 var(--font); }

/* "Last time": a black badge stuck across the card's top edge. A hint, not a choice: the card
   itself doesn't change, and the words say it */
.last-pick .c-last {
  position: absolute; z-index: 2; top: -14px; right: 14px;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px 5px 8px; border-radius: 999px;
  font: 900 10.5px/1 var(--font); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap;
  color: var(--lime); background: var(--ink);
  transform: rotate(2.5deg);
}
.last-pick .c-last::before {
  content: ""; flex: none; width: 12px; height: 12px; background: currentColor;
  -webkit-mask: var(--i-last) center / contain no-repeat; mask: var(--i-last) center / contain no-repeat;
}
.time-card.last-pick .c-last { right: auto; left: 14px; transform: rotate(-2.5deg); } /* the dial has the top right */

/* 1. what's tight: All over across the top, the six areas two by two, and Desk break, the quick
   start, across the bottom in lime. Each grey card has lime ink in its top corner, printed as a
   halftone: two sizes of dot on the ground's lattice, each wiped back to the card's grey beyond
   its reach (--g sets the reach) */
.focus-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: auto repeat(3, minmax(92px, 1fr)) auto; max-height: 660px; }
.focus-card {
  --g: 1;
  background:
    radial-gradient(circle at 100% 0, rgba(155, 155, 155, 0) calc(var(--g) * 10%), var(--grey-2) calc(var(--g) * 27%)),
    var(--d-lime-1) 0 0 / var(--screen), var(--d-lime-1) 7px 7px / var(--screen),
    radial-gradient(circle at 100% 0, rgba(155, 155, 155, 0) 0, var(--grey-2) calc(var(--g) * 15%)),
    var(--d-lime-2) 0 0 / var(--screen), var(--d-lime-2) 7px 7px / var(--screen),
    var(--grey-2);
}
/* an arrow at the top right: this one leads on to the next question (the name keeps clear of it) */
.focus-card .c-name { position: relative; align-self: stretch; padding-right: 26px; }
.focus-card .c-name::after {
  content: ""; position: absolute; top: -1px; right: -4px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--ink);
  -webkit-mask: none; mask: none;
}
.focus-card .c-name::before {
  content: ""; position: absolute; z-index: 1; top: 3px; right: 0; width: 16px; height: 16px;
  background: var(--lime);
  -webkit-mask: var(--i-arrow) center / contain no-repeat; mask: var(--i-arrow) center / contain no-repeat;
  transition: transform .4s var(--spring);
}
@media (hover: hover) { .focus-card:hover .c-name::before { transform: translateX(2px); } }
.focus-card:first-child { --g: .55; grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; align-items: baseline; column-gap: 10px; min-height: 60px; justify-content: flex-start; padding-right: 50px; }
.focus-card:first-child .c-name { font-size: 21px; align-self: auto; padding-right: 0; position: static; }
.focus-card:first-child .c-name::after { top: 50%; right: 14px; margin-top: -12px; }
.focus-card:first-child .c-name::before { top: 50%; right: 18px; margin-top: -8px; }
.desk-card {
  --off: 6px;
  grid-column: 1 / -1; min-height: 84px; padding: 15px 78px 15px 17px; justify-content: center;
  background:
    radial-gradient(circle at 100% 100%, rgba(85, 255, 0, 0) 0, var(--lime) 36%),
    var(--d-press) 0 0 / var(--screen), var(--d-press) 7px 7px / var(--screen),
    var(--lime);
}
.desk-card .c-name { font-size: 24px; letter-spacing: -.02em; padding-right: 0; }
.desk-card .c-name::before, .desk-card .c-name::after { content: none; }
.desk-card .c-note { font-weight: 700; }
.desk-card .c-tag {
  position: absolute; z-index: 2; top: -14px; left: 16px;
  padding: 5px 10px; border-radius: 999px;
  font: 900 10.5px/1 var(--font); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap;
  color: var(--lime); background: var(--ink);
  transform: rotate(-2deg);
}
/* the play disc on every card that starts a session: black, the play sign in lime, a white
   highlight under it (decoration: the whole card is the button) */
.desk-card::after, .hold-card::after {
  content: ""; position: absolute; right: 15px; top: 50%; width: 50px; height: 50px; margin-top: -25px; border-radius: 50%; pointer-events: none;
  background: var(--i-play-lime) 57% 50% / 22px no-repeat, var(--ink);
  box-shadow: 3px 3px 0 var(--paper), 3px 3px 0 3px var(--ink);
  transition: transform .4s var(--spring);
}
@media (hover: hover) { .desk-card:hover::after, .hold-card:hover::after { transform: scale(1.06); } }

/* 2. how long: the five lengths, two by two and the works across the bottom. Each is a grey
   sticker with lime ink printed in its corner as a halftone (reaching further the longer the
   session), a little dial showing its share of an hour, and the logo's lettering for the number */
.time-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(3, minmax(108px, 1fr)); max-height: 560px; }
.time-grid .time-card:last-child { grid-column: 1 / -1; }
.time-card {
  --card: var(--grey-2); --share: 30deg; --g: .55; --at: 100% 0;
  justify-content: flex-end; gap: 8px; padding: 14px 16px 15px; line-height: 1;
  background:
    radial-gradient(circle at var(--at), rgba(155, 155, 155, 0) calc(var(--g) * 22%), var(--card) calc(var(--g) * 48%)),
    var(--d-lime-1) 0 0 / var(--screen), var(--d-lime-1) 7px 7px / var(--screen),
    radial-gradient(circle at var(--at), rgba(155, 155, 155, 0) calc(var(--g) * 11%), var(--card) calc(var(--g) * 31%)),
    var(--d-lime-2) 0 0 / var(--screen), var(--d-lime-2) 7px 7px / var(--screen),
    radial-gradient(circle at var(--at), rgba(155, 155, 155, 0) 0, var(--card) calc(var(--g) * 17%)),
    var(--d-lime-3) 0 0 / var(--screen), var(--d-lime-3) 7px 7px / var(--screen),
    var(--card);
}
.time-card:nth-child(2) { --share: 60deg; --g: .78; }
.time-card:nth-child(3) { --share: 90deg; --g: 1; }
.time-card:nth-child(4) { --share: 120deg; --g: 1.22; }
.time-card:nth-child(5) { --share: 180deg; --g: .95; --at: 100% 100%; } /* the works: the lime rises from the far corner */
.time-card .t-num {
  --o: .06em; --dx: .05em; --dy: .055em;
  position: relative; display: flex; align-items: baseline;
  font: italic 900 54px/.92 var(--font); letter-spacing: -.02em; font-variant-numeric: tabular-nums;
  padding-left: .04em;
}
.time-card .t-unit {
  margin-left: 7px; font: italic 900 16px/1 var(--font); letter-spacing: 0;
  color: var(--ink); -webkit-text-stroke: 0; text-shadow: none;
}
.time-card .t-tag { display: block; font: 700 13.5px/1.25 var(--font); color: var(--ink); }
/* the dial: a little stopwatch face, its share of an hour a lime wedge edged in black (placed
   against the card) */
.time-card .t-tag::before {
  content: ""; position: absolute; top: 14px; right: 14px; width: 32px; height: 32px; border-radius: 50%;
  background: conic-gradient(var(--ink) 0 4deg, var(--lime) 0 calc(var(--share) - 4deg), var(--ink) 0 var(--share), var(--grey-3) 0);
  box-shadow: 0 0 0 2.5px var(--ink), 2.5px 2.5px 0 2.5px var(--ink);
}
.time-card:last-child .t-num { font-size: 60px; }

/* 3. how long a hold: three lime cards, each starts the session. A bar shows how long a hold is */
.hold-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: repeat(3, minmax(104px, 1fr)); max-height: 470px; }
.hold-card {
  --off: 6px; --len: 66%;
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto; align-content: center; align-items: center;
  column-gap: 10px; row-gap: 7px; padding: 15px 80px 30px 18px;
  background:
    radial-gradient(circle at 100% 0, rgba(85, 255, 0, 0) 0, var(--lime) 32%),
    var(--d-press) 0 0 / var(--screen), var(--d-press) 7px 7px / var(--screen),
    var(--lime);
}
.hold-card:nth-child(1) { --len: 44%; }
.hold-card:nth-child(3) { --len: 100%; }
.hold-card .c-name { grid-column: 1; grid-row: 1; font-size: 27px; letter-spacing: -.02em; }
.hold-card .c-secs {
  grid-column: 2; grid-row: 1; justify-self: start;
  padding: 4px 10px; border-radius: 999px;
  font: italic 900 15px/1 var(--font); font-variant-numeric: tabular-nums; color: var(--lime); background: var(--ink);
}
.hold-card .c-note { grid-column: 1 / -1; grid-row: 2; font-weight: 700; font-size: 13.5px; }
/* the bar, along the bottom (hung off the seconds: the card's own pseudo-elements are taken) */
.hold-card .c-secs::after {
  content: ""; position: absolute; left: 18px; right: 80px; bottom: 14px; height: 10px; border-radius: 6px;
  background: linear-gradient(90deg, var(--ink) 0 var(--len), var(--paper) 0) no-repeat;
  box-shadow: 0 0 0 2.5px var(--ink);
}

/* ---------- play ---------- */

#play { gap: 10px; }
.play-top { display: flex; align-items: center; gap: 12px; flex-shrink: 0; min-height: 50px; }
.play-top .routine-title {
  flex: 1; min-width: 0;
  font: italic 800 14px/1.22 var(--font); letter-spacing: .005em; color: var(--ink);
  overflow: hidden; text-wrap: balance;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
/* time left: lime numerals printed on a black pill, with a lime dot */
.play-top .total-remaining {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  min-height: 38px; margin-right: 4px; padding: 0 14px 0 12px; border-radius: 999px;
  font: 800 16px/1 var(--font); font-variant-numeric: tabular-nums; letter-spacing: .01em; color: var(--lime);
  background: var(--ink);
}
.play-top .total-remaining::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--lime); }

.play-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  min-height: 0;
  text-align: center;
  container-type: size; /* the numerals size themselves to this area's real height (cqh) */
}
/* when a long name, a note and a tall photo all land on a small phone, the photo is the one
   thing that gives way (it keeps its shape: its width follows its height); every line of text
   keeps its full height */
.play-main > * { flex-shrink: 0; }

/* the phase: a pill that says it, and changes with it (colour only, never motion). Get ready is
   black with a hollow dot; Hold is the live one, a lime sticker with a solid dot; on a rep the pill
   points the way (Lower: black, an arrow down; Up: lime, an arrow up); paused is pale grey with a
   pause sign. The word always says it, so colour is never the only signal */
.phase-label {
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 34px; padding: 0 16px 0 13px; border-radius: 999px;
  font: 900 13px/1 var(--font); letter-spacing: .2em; text-transform: uppercase;
  color: var(--grey-3); background: var(--ink);
  border: var(--line) solid var(--ink);
}
.phase-label::before { content: ""; flex: none; width: 10px; height: 10px; border-radius: 50%; box-shadow: inset 0 0 0 2.5px currentColor; }
.phase-label:empty { visibility: hidden; }
.phase-label.holding { color: var(--ink); background: var(--lime); box-shadow: var(--sh-s); }
.phase-label.holding::before { background: currentColor; }
.phase-label.lowering, .phase-label.up { gap: 7px; }
.phase-label.lowering { color: var(--lime); }
.phase-label.up { color: var(--ink); background: var(--lime); box-shadow: var(--sh-s); }
.phase-label.lowering::before, .phase-label.up::before {
  width: 13px; height: 13px; border-radius: 0; box-shadow: none; background: currentColor;
  -webkit-mask: var(--i-down) center / contain no-repeat; mask: var(--i-down) center / contain no-repeat;
}
.phase-label.up::before { -webkit-mask-image: var(--i-up); mask-image: var(--i-up); }

.stretch-title {
  max-width: 100%; padding: 12px 6px 0;
  font: italic 900 clamp(24px, 6.8vw, 32px)/1.12 var(--font); letter-spacing: -.012em;
  color: var(--ink); text-wrap: balance;
}
.side-chip {
  display: inline-flex; align-items: center; min-height: 30px; margin-top: 8px; padding: 0 16px;
  border-radius: 999px; visibility: hidden;
  font: italic 900 clamp(14px, 4vmin, 17px)/1 var(--font); letter-spacing: .01em; color: var(--lime);
  background: var(--ink);
}
.side-chip.visible { visibility: visible; }

/* the photo, a sticker like everything else: cut out in black on a hard shadow. Some are photos,
   some illustrations, a few carry watermarks: all shown as they are */
.stretch-img {
  display: none;
  flex: 0 1 auto; min-height: 84px;
  max-width: min(calc(100% - 24px), 340px);
  max-height: 28vh;
  max-height: 28dvh;
  margin: 16px 0 18px;
  object-fit: contain;
  border: var(--line) solid var(--ink); border-radius: 18px;
  background: var(--paper);
  box-shadow: var(--sh);
  transition: filter .3s var(--ease);
}
.stretch-img.visible { display: block; }

/* the countdown: the logo's lettering, huge and crisp, standing on the plain dot screen with
   nothing behind it (no ring, no halo, no glow) and nothing moving. The phases recolour it:
   get ready pale, holding lime, the last three seconds the logo inside out (black in a lime
   edge), paused grey */
.countdown {
  --o: .05em; --dx: .042em; --dy: .048em; --dil: .026em;
  position: relative;
  margin: 4px 0 10px; padding: 0 .1em .02em .06em;
  font: italic 900 clamp(80px, min(36vmin, 17dvh), 200px)/1 var(--font);
  font-size: clamp(80px, min(36vmin, 22cqh), 200px);
  letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
/* a note on screen (two or three lines of it): the numerals give the photo a little room back */
.play-main:has(> .step-note:not([hidden])) .countdown:not(.reps) { font-size: clamp(80px, min(36vmin, 19.5cqh), 200px); }
.countdown.lead { --fill: var(--grey-3); }
.countdown.ending { --fill: var(--ink); --edge: var(--lime); }
/* a rep count: smaller, its total in pale grey */
.countdown.reps { font-size: clamp(60px, min(22vmin, 11.5dvh), 140px); font-size: clamp(60px, min(22vmin, 15cqh), 140px); }
.countdown.reps .of { --fill: var(--grey-3); font-size: .42em; letter-spacing: 0; }

/* the rep cadence: a lime bar that fills on the way down and drains on the way up (striped on
   the way up, so the two halves differ in more than direction) */
.cadence {
  width: min(78%, 300px); height: 18px; margin: 10px auto 0; border-radius: 999px; overflow: hidden;
  background: var(--grey-2); border: var(--line) solid var(--ink); box-shadow: var(--sh-s);
}
.cadence-fill {
  height: 100%; width: 0%; border-radius: 999px;
  background: var(--lime); box-shadow: 3px 0 0 var(--ink);
  transition: width .1s linear; /* smooths the app's ten steps a second */
}
.cadence-fill.up { background: repeating-linear-gradient(-45deg, var(--lime) 0 5px, var(--ink) 5px 8px); }

/* the step's note: a pale sticker with a lime tab */
.step-note {
  position: relative; max-width: min(calc(100% - 8px), 460px); margin: 14px auto 0;
  padding: 9px 14px 10px 24px; border-radius: var(--r-m);
  font: 600 clamp(13.5px, 3.6vmin, 16px)/1.4 var(--font); color: var(--ink); text-align: left;
  background: var(--grey-3); border: var(--line) solid var(--ink); box-shadow: var(--sh-s);
}
.step-note::before {
  content: ""; position: absolute; left: 7px; top: 9px; bottom: 9px; width: 7px; border-radius: 4px;
  background: var(--lime); box-shadow: 0 0 0 2px var(--ink);
}
/* no photo (Desk break's stretches): the instructions ARE the picture. The numerals take more of
   the room, and the note grows into the main thing to read, with a "How to" tag stuck on it */
.play-main:has(> .stretch-img:not(.visible)) .countdown:not(.reps) {
  margin-top: 14px;
  font-size: clamp(80px, min(46vmin, 27cqh), 200px);
}
.stretch-img:not(.visible) ~ .step-note {
  max-width: min(calc(100% - 10px), 440px); margin-top: 26px; padding: 20px 18px 16px 32px;
  font-size: clamp(16px, 4.5vmin, 19px); font-weight: 600; line-height: 1.42;
  border-radius: var(--r-l);
  box-shadow: var(--sh);
}
.stretch-img:not(.visible) ~ .step-note::before { left: 10px; top: 16px; bottom: 16px; width: 9px; }
.stretch-img:not(.visible) ~ .step-note::after {
  content: "How to"; content: "How to" / "";
  position: absolute; top: -14px; left: 20px;
  padding: 5px 11px; border-radius: 999px;
  font: 900 10.5px/1 var(--font); letter-spacing: .15em; text-transform: uppercase; white-space: nowrap;
  color: var(--lime); background: var(--ink);
  transform: rotate(-2deg);
}
.intensity {
  max-width: min(94%, 460px); margin-top: 12px;
  font: italic 600 clamp(12.5px, 3.3vmin, 14px)/1.35 var(--font); color: var(--ink);
}
.next-up {
  max-width: 100%; height: 22px; margin-top: 8px;
  font: 500 clamp(14px, 4vmin, 16.5px)/22px var(--font); color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.next-up b { font-weight: 900; font-style: italic; }

/* the controls: round grey stickers either side of the one lime button */
.play-controls {
  display: flex; justify-content: center; align-items: center; gap: 14px;
  flex-shrink: 0; padding: 4px 5px 8px 0;
}
.play-controls button {
  position: relative; flex: none; width: 56px; height: 56px; border-radius: 50%;
  background: var(--grey-2);
  border: var(--line) solid var(--ink);
  box-shadow: 4px 4px 0 var(--ink);
  transition: transform .4s var(--spring), box-shadow .2s var(--ease), background-color .15s var(--ease);
}
.play-controls button::before { width: 24px; height: 24px; }
@media (hover: hover) {
  .play-controls button:hover { background-color: var(--grey-3); transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--ink); }
}
.play-controls button:active { transform: translate(3px, 3px); box-shadow: 1px 1px 0 var(--ink); transition-duration: .08s; }
.play-controls .big {
  width: 100px; height: 68px; border-radius: 999px;
  background: var(--lime);
  box-shadow: var(--sh);
}
.play-controls .big::before { width: 30px; height: 30px; }
@media (hover: hover) {
  .play-controls .big:hover { background-color: var(--lime); transform: translate(-1px, -1px); box-shadow: 6px 6px 0 var(--ink); }
}
.play-controls .big:active { transform: translate(4px, 4px); box-shadow: 1px 1px 0 var(--ink); }
/* finished: nothing left to pause, so the button steps back to grey with a tick */
#btnPlayPause[aria-label="Finished"] { background: var(--grey-2); box-shadow: 4px 4px 0 var(--ink); cursor: default; transform: none; }

/* the whole session: a lime bar in a black-cut track, with a white knob at its head */
.progress-track {
  flex-shrink: 0; height: 16px; margin: 2px 10px 4px 6px; border-radius: 999px;
  background: var(--grey-2); border: var(--line) solid var(--ink); box-shadow: var(--sh-s);
}
.progress-fill {
  position: relative; height: 100%; width: 0%; min-width: 8px; border-radius: inherit;
  background: var(--lime);
}
.progress-fill::after {
  content: ""; position: absolute; right: -9px; top: 50%; width: 18px; height: 18px; margin-top: -9px; border-radius: 50%;
  background: var(--paper); box-shadow: 0 0 0 3px var(--ink), 2px 2px 0 3px var(--ink);
}
.kbd-hint { flex-shrink: 0; font-size: 12px; font-weight: 700; text-align: center; color: var(--ink); }
.kbd-hint kbd {
  display: inline-block; min-width: 22px; padding: 2px 6px; margin: 0 1px; border-radius: 6px;
  font: 800 11.5px/1.2 var(--font); color: var(--lime);
  background: var(--ink);
}
/* keyboard shortcuts mean nothing on a phone */
@media (hover: none) { .kbd-hint { display: none; } }

/* paused: the pill goes pale with a pause sign, the numerals grey out and the photo with them.
   Still, like the rest of a session: the lime button says what to press */
#play:has(#btnPlayPause[aria-label="Resume"]) .phase-label { color: var(--ink); background: var(--grey-3); box-shadow: var(--sh-s); }
#play:has(#btnPlayPause[aria-label="Resume"]) .phase-label::before {
  width: 12px; height: 13px; border-radius: 0; box-shadow: none; background: currentColor;
  -webkit-mask: var(--i-pause) center / 15px 15px no-repeat; mask: var(--i-pause) center / 15px 15px no-repeat;
}
#play:has(#btnPlayPause[aria-label="Resume"]) .countdown, #play:has(#btnPlayPause[aria-label="Resume"]) .countdown .of { --fill: var(--grey-2); --edge: var(--ink); }
#play:has(#btnPlayPause[aria-label="Resume"]) .stretch-img { filter: grayscale(1); }
#play:has(#btnPlayPause[aria-label="Resume"]) .cadence-fill { transition: none; }

/* ---------- finished: a ticket ---------- */

/* the biggest sticker of all: a grey ticket with lime ink rising out of its corner, cut out in
   black with a notch either side of the perforation, on its own hard shadow */
.finish-box {
  --stub: 88px; /* bottom edge to the perforation: 18px padding + 50px buttons + half the 40px gap */
  --ticket-mask:
    radial-gradient(circle 13px at 0 calc(100% - var(--stub)), rgba(0, 0, 0, 0) 12.5px, #000 13px) left / 51% 100% no-repeat,
    radial-gradient(circle 13px at 100% calc(100% - var(--stub)), rgba(0, 0, 0, 0) 12.5px, #000 13px) right / 51% 100% no-repeat;
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; align-items: flex-start;
  width: min(calc(100% - 10px), 372px); margin-right: 10px; padding: 24px 22px 18px; color: var(--ink); text-align: left;
  animation: ffx-ticket .8s var(--slap) backwards;
}
/* the hard shadow: the ticket's own shape, notches and all, set down behind it */
.finish-box::before {
  content: ""; position: absolute; inset: 0; z-index: -3; border-radius: var(--r-l); pointer-events: none;
  background: var(--ink);
  transform: translate(7px, 7px);
  -webkit-mask: var(--ticket-mask); mask: var(--ticket-mask);
}
/* the ticket: grey card, lime halftone from the top left, cut out in black (the notches get their
   black edge from two discs the mask bites into) */
.finish-box::after {
  --at: 0 0;
  content: ""; position: absolute; inset: 0; z-index: -2; border-radius: var(--r-l); pointer-events: none;
  background:
    radial-gradient(circle 16px at 0 calc(100% - var(--stub)), var(--ink) 15.5px, rgba(0, 0, 0, 0) 16px),
    radial-gradient(circle 16px at 100% calc(100% - var(--stub)), var(--ink) 15.5px, rgba(0, 0, 0, 0) 16px),
    radial-gradient(circle at var(--at), rgba(155, 155, 155, 0) 18%, var(--grey-2) 44%),
    var(--d-lime-1) 0 0 / var(--screen), var(--d-lime-1) 7px 7px / var(--screen),
    radial-gradient(circle at var(--at), rgba(155, 155, 155, 0) 8%, var(--grey-2) 28%),
    var(--d-lime-2) 0 0 / var(--screen), var(--d-lime-2) 7px 7px / var(--screen),
    radial-gradient(circle at var(--at), rgba(155, 155, 155, 0) 0, var(--grey-2) 15%),
    var(--d-lime-3) 0 0 / var(--screen), var(--d-lime-3) 7px 7px / var(--screen),
    var(--grey-2);
  box-shadow: inset 0 0 0 var(--line) var(--ink);
  -webkit-mask: var(--ticket-mask); mask: var(--ticket-mask);
}
/* the party popper becomes a black tile with a lime tick, slapped on at an angle, and "Session
   complete" beside it (it's aria-hidden, so this is decoration only) */
.finish-box .big-check {
  position: relative; flex: none; width: 48px; height: 48px; border-radius: var(--r-m);
  font-size: 0; color: transparent; overflow: visible;
  background: var(--i-check-lime) center / 28px no-repeat, var(--ink);
  transform: rotate(-4deg);
  animation: ffx-badge .6s var(--slap) .3s backwards;
}
.finish-box .big-check::after {
  content: "Session complete"; content: "Session complete" / "";
  position: absolute; left: 62px; top: 50%; transform: translateY(-50%) rotate(4deg); white-space: nowrap;
  font: 900 12px/1.2 var(--font); letter-spacing: .16em; text-transform: uppercase; color: var(--ink);
}
.finish-box h2 { margin: 16px 52px 0 0; font-size: 68px; line-height: 1; letter-spacing: -.02em; padding: 0 .08em .06em 0; }
/* a shine across it as it lands (once), over the ticket's face (z -2) and under the lettering */
.finish-box h2::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: var(--r-l); pointer-events: none;
  background: linear-gradient(105deg, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, .6) 42% 46%, rgba(255, 255, 255, 0) 46% 48%, rgba(255, 255, 255, .6) 48% 49.5%, rgba(255, 255, 255, 0) 49.5%) 160% 0 / 260% 100% no-repeat;
  -webkit-mask: var(--ticket-mask); mask: var(--ticket-mask);
  animation: ffx-sheen 1.1s .55s ease-in-out backwards;
  text-shadow: none;
}
/* and the small print up its side (decoration: screen readers skip it) */
.finish-box h2::after {
  content: "Admit one \B7  Stretcher"; content: "Admit one \B7  Stretcher" / "";
  position: absolute; top: 24px; right: 55px; writing-mode: vertical-rl; white-space: nowrap;
  font: 900 8px/1 var(--font); letter-spacing: .22em; text-transform: uppercase; color: var(--ink);
  -webkit-text-stroke: 0; text-shadow: none;
}
.finish-box .meta { margin: 10px 52px 0 0; font: italic 800 19px/1.25 var(--font); letter-spacing: -.005em; color: var(--ink); }
/* a tall barcode down the right, because it's a ticket */
.finish-box .meta::after {
  content: ""; position: absolute; top: 24px; right: 22px; bottom: calc(var(--stub) + 16px); width: 26px;
  background: linear-gradient(180deg,
    var(--ink) 0 2px, #0000 0 4px, var(--ink) 0 5px, #0000 0 7px, var(--ink) 0 10px, #0000 0 11px, var(--ink) 0 12px,
    #0000 0 14px, var(--ink) 0 15px, #0000 0 17px, var(--ink) 0 20px, #0000 0 21px, var(--ink) 0 22px, #0000 0 24px,
    var(--ink) 0 26px, #0000 0 28px, var(--ink) 0 29px, #0000 0 30px, var(--ink) 0 33px, #0000 0 35px, var(--ink) 0 36px,
    #0000 0 37px, var(--ink) 0 38px, #0000 0 40px, var(--ink) 0 43px, #0000 0 44px, var(--ink) 0 45px, #0000 0 47px,
    var(--ink) 0 49px, #0000 0 51px, var(--ink) 0 52px, #0000 0 53px, var(--ink) 0 56px, #0000 0 57px, var(--ink) 0 58px, #0000 0 60px)
    0 0 / 100% 60px repeat-y;
}
.finish-box .btns { display: flex; gap: 12px; width: 100%; margin-top: 40px; }
/* the perforation above the stub */
.finish-box .btns::before {
  content: ""; position: absolute; left: 16px; right: 16px; bottom: calc(var(--stub) - 3px); height: 6px; pointer-events: none;
  background: radial-gradient(circle, var(--ink) 1.7px, rgba(0, 0, 0, 0) 2.3px) 0 0 / 12px 6px repeat-x;
}
.finish-box .btns button {
  position: relative; flex: 1 1 auto; min-height: 50px; padding: 0 16px; border-radius: 999px;
  font: italic 900 15.5px/1.1 var(--font); letter-spacing: -.005em; white-space: nowrap;
  color: var(--ink); background: var(--grey-3);
  border: var(--line) solid var(--ink); box-shadow: var(--sh-s);
  transition: transform .4s var(--spring), box-shadow .2s var(--ease), background-color .15s var(--ease);
}
@media (hover: hover) { .finish-box .btns button:hover { background-color: var(--paper); transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--ink); } }
.finish-box .btns button:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); transition-duration: .08s; }
/* the one to press: lime, like every other go */
.finish-box .btns .primary { background: var(--lime); }
@media (hover: hover) { .finish-box .btns .primary:hover { background-color: var(--lime); } }

/* ---------- "alright powelly": an incoming text (app.js; on average once every three hours open) ---------- */

/* a lime speech bubble stuck to the top of the screen: cut out in black on its hard shadow, with
   a tail at the bottom left, the sender's black avatar disc and the words in heavy italic black
   (15:1 on lime). It drops in from above and slaps down at a slight tilt; a tap anywhere on it
   sends it back up (the app takes the class off, then the element). Under reduced motion it
   simply appears and goes */
.powelly {
  position: fixed; z-index: 300;
  top: max(14px, env(safe-area-inset-top)); left: 16px; right: 22px; /* room for the shadow on the right */
  max-width: 380px; margin: 0 auto;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 5px 10px;
  padding: 10px 16px 13px 11px; border-radius: 22px 22px 22px 9px;
  color: var(--ink); background: var(--lime);
  border: var(--line) solid var(--ink); box-shadow: var(--sh);
  cursor: pointer; touch-action: manipulation;
  transform: translateY(calc(-100% - 70px)) rotate(-5deg);
  transition: transform .3s cubic-bezier(.55, 0, .85, .25); /* going: up and away, quick */
}
.powelly-in { transform: rotate(-1.5deg); transition: transform .6s var(--slap); } /* arriving: slapped down */
/* the tail: drawn as one small picture (its outline, its lime, and its own hard shadow) that
   covers the bubble's outline where it joins, so the two read as one cut-out */
.powelly::after {
  content: ""; position: absolute; top: 100%; left: 14px; width: 38px; height: 32px; margin-top: -1px; pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 38 32'%3E%3Cpath d='M14 6C14 16 12 22 8 29C18 27 27 20 34 9V6z' stroke='%23000' stroke-width='3' stroke-linejoin='round'/%3E%3Cpath d='M9 0C9 11 7 17 3 24C13 22 22 15 29 4V0z' fill='%2355ff00'/%3E%3Cpath d='M9 1C9 11 7 17 3 24C13 22 22 15 29 4V1' fill='none' stroke='%23000' stroke-width='3' stroke-linejoin='round'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
}
.powelly-from {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  font: 900 12px/1 var(--font); letter-spacing: .16em; text-transform: uppercase;
}
/* the sender's avatar: a black disc with the S in lime (decoration: screen readers skip it) */
.powelly-from::before {
  content: "S"; content: "S" / "";
  flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  font: italic 900 15px/1 var(--font); letter-spacing: 0; text-transform: none; color: var(--lime); background: var(--ink);
}
.powelly-from { grid-column: 1; grid-row: 1; }
.powelly-time { grid-column: 2; grid-row: 1; font: 800 11.5px/1 var(--font); letter-spacing: .12em; text-transform: uppercase; }
.powelly-text { grid-column: 1 / -1; grid-row: 2; padding: 0 0 0 34px; font: italic 900 24px/1.1 var(--font); letter-spacing: -.01em; }

/* ---------- motion ---------- */

/* screens settle into place as they appear (the app swaps them with the hidden attribute, and
   an element coming out of display:none starts its animations afresh). Transform only: content
   is readable from the first frame. Stickers don't fade in: they get slapped down. All of it
   once; nothing on the play screen ever loops */
.topbar { animation: ffx-drop .45s var(--ease) backwards; }
.hero { animation: ffx-rise .5s var(--ease) backwards; }
.play-top { animation: ffx-drop .45s var(--ease) backwards; }
.phase-label, .stretch-title, .side-chip, .step-note, .next-up { animation: ffx-rise .45s var(--ease) backwards; }
/* (not the intensity line or the cadence bar: the app shows and hides those as each hold or rep
   starts, which would replay an entrance right under the numerals every stretch) */
.stretch-title { animation-delay: .03s; }
.side-chip { animation-delay: .06s; }
.stretch-img { animation: ffx-slap .55s var(--slap) .08s backwards; }
.play-controls, .progress-track, .kbd-hint { animation: ffx-rise .5s var(--ease) .1s backwards; }

@keyframes ffx-stretch { from { transform: scaleX(.25); } }
@keyframes ffx-rise { from { transform: translateY(14px); } }
@keyframes ffx-drop { from { transform: translateY(-8px); } }
@keyframes ffx-pop { from { transform: scale(.85); } }
@keyframes ffx-slap { from { transform: translateY(16px) rotate(-2.5deg) scale(.94); } }
@keyframes ffx-badge { from { transform: scale(0) rotate(-30deg); } }
@keyframes ffx-ticket { from { transform: translateY(24px) rotate(-3deg) scale(.94); } }
@keyframes ffx-sheen { from { background-position: 160% 0; } to { background-position: -60% 0; } }

/* everything stops, and the page still looks finished */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
  /* presses and hovers answer with the shadow only: nothing moves */
  .card:active, .card:hover, .step-back:active, .step-back:hover, button.icon:active, button.icon:hover, #btnSettings[aria-expanded="true"],
  .play-controls button:active, .play-controls button:hover, .finish-box .btns button:active, .finish-box .btns button:hover { transform: none; }
  .desk-card:hover::after, .hold-card:hover::after, .focus-card:hover .c-name::before { transform: none; }
}

/* ---------- sizes ---------- */

@media (max-width: 360px) {
  :root { --gutter: 12px; }
  .brand { font-size: 28px; }
  .hero-title { font-size: 34px; }
  .hero-kicker { letter-spacing: .12em; }
  .cards { gap: 13px 10px; }
  .card { padding: 13px 13px 14px; }
  .c-name { font-size: 17px; }
  .c-note { font-size: 12.5px; }
  .time-card .t-num { font-size: 48px; }
  .time-card:last-child .t-num { font-size: 54px; }
  .desk-card, .hold-card { padding-right: 72px; }
  .desk-card::after, .hold-card::after { right: 12px; width: 46px; height: 46px; margin-top: -23px; }
  .hold-card .c-secs::after { right: 72px; }
  .play-controls { gap: 12px; }
  .finish-box { padding: 22px 18px 18px; }
  .finish-box h2 { font-size: 60px; margin-right: 44px; }
  .finish-box .meta { margin-right: 44px; font-size: 17.5px; }
  .finish-box .meta::after { right: 18px; width: 22px; }
  .finish-box h2::after { right: 47px; }
  .finish-box .btns button { padding: 0 12px; font-size: 15px; }
}
/* short phones: the cards give up a little height (and the title fits one line), so a step still fits */
@media (max-height: 780px) {
  .hero-title { font-size: min(38px, 8.6vw); }
  .cards { margin-top: 14px; row-gap: 13px; }
  .focus-grid { grid-template-rows: auto repeat(3, minmax(84px, 1fr)) auto; }
  .time-grid { grid-template-rows: repeat(3, minmax(98px, 1fr)); }
  .hold-grid { grid-template-rows: repeat(3, minmax(98px, 1fr)); }
  /* and the play screen's spacing tightens first, so the photo keeps more of its size */
  .stretch-title { padding-top: 8px; }
  .stretch-img { margin: 14px 0 14px; }
  .step-note { margin-top: 12px; }
  .intensity { margin-top: 10px; }
}
/* short phones (and landscape): the photo gives a little room back */
@media (max-height: 700px) {
  .stretch-img { max-height: 24vh; max-height: 24dvh; margin: 14px 0 12px; }
}

@media (min-width: 700px) {
  .hero-title { font-size: 46px; }
  .time-card .t-num { font-size: 60px; }
  .time-card:last-child .t-num { font-size: 66px; }
}

/* more contrast asked for: the dot screens come off the ground and the cards, edges stay */
@media (prefers-contrast: more) {
  body::before { background: var(--grey); }
  body::after { content: none; }
  .focus-card, .time-card, .finish-box::after { background: var(--grey-3); }
  .desk-card, .hold-card { background: var(--lime); }
  .finish-box::after { box-shadow: inset 0 0 0 var(--line) var(--ink); }
}

/* Windows high contrast: the app's own glyphs come back, every edge and state stays visible */
@media (forced-colors: active) {
  #btnSettings, #btnExit { font-size: 22px; }
  .play-controls button { font-size: 20px; }
  #btnSettings::before, #btnExit::before, .play-controls button::before { display: none; }
  button.icon, .play-controls button, .card, .step-back, .last-pick .c-last, .c-tag, .hold-card .c-secs, .settings-panel, .step-note, .phase-label, .side-chip, .finish-box, .finish-box .btns button, .cadence, .progress-track, .powelly { border: 1px solid CanvasText; }
  .powelly::after { display: none; }
  .card::after, .desk-card::after, .hold-card::after, .hold-card .c-secs::after, .time-card .t-tag::before, .focus-card .c-name::before, .focus-card .c-name::after,
  .hero-kicker::before, .last-pick .c-last::before, .finish-box::before, .finish-box::after, .finish-box h2::before, .finish-box .meta::after, .finish-box .btns::before,
  body::before, body::after, .brand::after, .phase-label::before, .progress-fill::after, .step-note::before { display: none; }
  .logo-text, .countdown, .time-card .t-num, .countdown .of, .c-name { -webkit-text-stroke: 0; text-shadow: none; color: CanvasText; }
  .progress-fill, .cadence-fill { background: Highlight; }
  .finish-box .big-check { font-size: 48px; color: CanvasText; background: none; }
}

/* =========================================================================================
   Effects. The look's script (frizzy.js) adds the ffx- classes below while it runs: only on
   Frizzy G, only when motion is allowed, and it takes every one of them away again when the
   look changes. Without it none of them exist and everything above is the whole look.
   ========================================================================================= */

:root { --frizzy-fx: on; } /* tells the script this sheet is live (the switch can load sheets late) */

/* the live halftone: the same dot screen and swells, printed by the GPU over the CSS ground, that
   a finger stirs lime ink into on Home and at the finish. It fades in; for a session it's simply
   gone (at once, no fade: nothing moves behind the countdown), and if the GPU drops it the CSS
   ground is there underneath */
.ffx-sky { position: fixed; inset: 0; z-index: -2; display: block; width: 100%; height: 100%; pointer-events: none; opacity: 0; }
.ffx-sky.ffx-in { opacity: 1; transition: opacity .6s var(--ease); }

/* confetti, stars and sticker dots at the finish: one canvas, only while they fly. It sits BEHIND the
   screens (over the ground), so the burst comes out from behind the ticket and never covers its
   lettering, its buttons or the controls */
.ffx-burst { position: fixed; inset: 0; z-index: -1; display: block; width: 100%; height: 100%; pointer-events: none; }

@media (forced-colors: active) {
  .ffx-sky, .ffx-burst { display: none; }
}
