/* Liquid glass calculator · stage 8 — performance. The canvas's lower resolutions are drawn in its bottom-left
   corner and stretched from there (transform-origin); the slab is its own compositor layer only while it is away from
   home (.is-moving); and a hidden copy of the calculator is laid out once at idle (.stage.warm).

   Every size comes from one number, --key (a key's side), which app.js works out from the screen's width AND height
   for the layout in use. The proportions it uses (--gap-r, --pad-r, --display-r) are set by app.js too, so the sum it
   solves and the boxes drawn here always agree.

   1 tokens: primitive → semantic → component     2 the page             3 the calculator: display, bar, keys, labels
   4 the history tape's place                       5 the hint and toast   7 screens      8 when there is no WebGL
   9 reduced motion */

/* ---- 1. TOKENS ---- */
/* primitive: the raw values, named for what they are */
:root {
  --studio-50: #F6F6F8; --studio-100: #ECEDF1; --studio-200: #DFE0E6; --studio-500: #8B8E99; --studio-900: #22242C;
  --ink-900: #1D1E23; --ink-800: #23242A;
  --violet-500: #6B47FF;
  --white: #FFFFFF;

  --font-display: 'Inter Tight', 'Inter', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Inter', ui-sans-serif, system-ui, sans-serif;

  --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px;
  --radius-pill: 999px;
}

/* semantic: what each value is for on this page */
:root {
  --page: var(--studio-100);
  --on-page: var(--studio-900);
  --on-page-muted: var(--studio-500);
  --focus: var(--violet-500);
  --gutter: max(var(--space-4), env(safe-area-inset-left), env(safe-area-inset-right));
}

/* component: the calculator's sizes. --key and the ratios are written by app.js (fit) on .stage, so a new size
   restyles the calculator only, not the whole page; these are first-paint defaults */
.stage {
  --key: 72px; --gap-r: .175; --pad-r: .27; --display-r: 2.3; --cols: 4; --rows: 5;
  --key-gap: calc(var(--key) * var(--gap-r));
  --calc-pad: calc(var(--key) * var(--pad-r));
  --calc-radius: calc(var(--key) * .64);
  --display-h: calc(var(--key) * var(--display-r));
  --num-size: calc(var(--key) * 1.02);
  --expr-size: max(13px, calc(var(--key) * .22));
  --tool-size: max(36px, calc(var(--key) * .5));
  --key-label-size: calc(var(--key) * .42);
  --key-fn-size: calc(var(--key) * .33);
  --key-op-size: calc(var(--key) * .5);
  --key-sci-size: max(12px, calc(var(--key) * .27));
}
/* component: the calculator's inks (the tone below sets them for its studio) */
:root {
  --display-ink: var(--white);
  --display-shade: 0 1px 2px rgb(30 30 60 / .45), 0 4px 22px rgb(30 30 60 / .38);
  --expr-ink: rgb(255 255 255 / .85);
  --label-ink: var(--white);
  --label-shade: 0 1px 1px rgb(20 10 60 / .35), 0 2px 12px rgb(20 10 60 / .35);
  --tool-press: rgb(255 255 255 / .16);
}
/* the scientific layouts: a shorter number, so the wide display keeps its proportions */
.stage[data-layout="sci-wide"], .stage[data-layout="sci-tall"] { --num-size: calc(var(--key) * .86); }
/* a finger needs 44 px: the tool bar's buttons never get smaller than that on a touch screen */
@media (pointer: coarse) { .stage { --tool-size: max(44px, calc(var(--key) * .5)); } }

/* the tone (app.js sets html[data-tone]; stage 9 adds four more) */
:root[data-tone="classic"] {
  --display-ink: var(--ink-900); --display-shade: 0 1px 0 rgb(255 255 255 / .5); --expr-ink: var(--display-ink);
  --label-ink: var(--ink-800); --label-shade: 0 1px 0 rgb(255 255 255 / .55); --tool-press: rgb(29 30 35 / .07);
}

/* ---- 2. the page: a studio, nothing else ---- */
* { box-sizing: border-box; }
html { background: var(--page); -webkit-text-size-adjust: 100%; }
body { margin: 0; font-family: var(--font-body); color: var(--on-page); background: var(--page); -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent; overflow-x: hidden; }
button { font: inherit; color: inherit; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

.page { position: relative; min-height: 100svh; isolation: isolate; overflow: hidden; display: grid; place-items: center; }
.gl, .fallback-bg { position: absolute; inset: 0; width: 100%; height: 100%; z-index: -1; display: block; }
.gl { transform-origin: 0 100%; }   /* a lower resolution is drawn in its bottom-left corner and stretched (app.js) */
.fallback-bg { display: none; }
.stage { display: flex; flex-direction: column; align-items: center; gap: var(--space-5); max-width: 100%;
  padding: max(var(--space-4), env(safe-area-inset-top)) var(--gutter) max(var(--space-4), env(safe-area-inset-bottom)); }

/* ---- 3. the calculator ---- */
.calc-home { position: relative; display: flex; align-items: flex-start; }
/* the slab: transparent here — the canvas draws the glass exactly under it, moved by the same transform. While it is
   away from home it is its own compositor layer, so dragging it moves pixels instead of repainting the display */
.calc { position: relative; flex: none; width: calc(var(--cols) * var(--key) + (var(--cols) - 1) * var(--key-gap) + 2 * var(--calc-pad));
  padding: 0 var(--calc-pad) var(--calc-pad); border-radius: var(--calc-radius);
  touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; transform-origin: 50% 50%; }
.calc.is-moving { will-change: transform; }
.calc.is-dragging { cursor: grabbing; }

/* the display: the tool bar on top, then the sum as typed, then the number (the live result) */
.display { position: relative; display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-end; height: var(--display-h);
  padding: 0 calc(var(--key) * .1) calc(var(--key) * .14); }
.bar { position: absolute; top: calc(var(--calc-pad) * .55); left: calc(var(--calc-pad) * -.25); right: calc(var(--key) * .08);
  display: flex; align-items: center; justify-content: space-between; pointer-events: none; }
.tools { display: flex; gap: calc(var(--key) * .04); pointer-events: auto; }
.tool { display: grid; place-items: center; width: var(--tool-size); height: var(--tool-size); padding: 0; border: 0; border-radius: 50%;
  color: var(--display-ink); background: transparent; opacity: .72; cursor: pointer; transition: opacity .15s, background-color .15s; }
.tool:hover { opacity: 1; background: var(--tool-press); }
.tool[aria-pressed="true"], .tool[aria-expanded="true"] { opacity: 1; background: var(--tool-press); }
.tool svg { width: 56%; height: 56%; }
.flags { display: flex; gap: var(--space-2); margin: 0; font: 600 max(11px, calc(var(--key) * .16))/1 var(--font-body); letter-spacing: .06em;
  text-transform: uppercase; color: var(--display-ink); opacity: .6; }
.flag[hidden] { display: none; }

/* the sum as typed: two lines at most; longer, it becomes one line that scrolls to keep its end in view, fading out
   on the left (app.js sets .is-long and the scroll) */
.expr { max-width: 100%; max-height: calc(var(--expr-size) * 1.25 * 2); margin: 0; overflow: hidden; text-align: right;
  font: 400 var(--expr-size)/1.25 var(--font-display); color: var(--expr-ink); opacity: .7; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums; text-shadow: 0 1px 6px rgb(40 30 90 / .25); overflow-wrap: anywhere; }
.expr.is-long { white-space: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 2.5em); mask-image: linear-gradient(90deg, transparent, #000 2.5em); }
.expr.is-long::-webkit-scrollbar { display: none; }
.expr.is-error { opacity: .9; }
.readout { display: flex; justify-content: flex-end; width: 100%; }
.num { display: block; max-width: 100%; min-width: 44px; min-height: 44px; padding: 0; text-align: right; border: 0; background: none; cursor: copy; touch-action: pan-y;
  font: 200 var(--num-size)/1.02 var(--font-display); letter-spacing: -.035em; white-space: nowrap; font-variant-numeric: tabular-nums;
  color: var(--display-ink); text-shadow: var(--display-shade); }
.num:focus { outline: none; }
.num:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; border-radius: 8px; }

.keys { display: grid; grid-template-columns: repeat(var(--cols), var(--key)); grid-template-rows: repeat(var(--rows), var(--key)); gap: var(--key-gap); }
.key { position: relative; display: grid; place-items: center; width: var(--key); height: var(--key); padding: 0; border: 0; border-radius: var(--radius-pill);
  background: none; color: var(--label-ink); cursor: pointer; touch-action: manipulation; -webkit-user-select: none; user-select: none; will-change: transform; }
.key[hidden] { display: none; }
.key.zero { width: auto; justify-items: start; padding-left: calc(var(--key) / 2 - .3em); }
.lbl { display: block; font: 300 var(--key-label-size)/1 var(--font-display); letter-spacing: -.02em; pointer-events: none; text-shadow: var(--label-shade); white-space: nowrap; }
.key.fn .lbl { font-size: var(--key-fn-size); font-weight: 400; }
.key.op .lbl { font-size: var(--key-op-size); font-weight: 300; margin-top: -2px; }
.key.sci .lbl { font-size: var(--key-sci-size); font-weight: 400; letter-spacing: 0; }
.lbl sup, .lbl sub { font-size: .66em; line-height: 0; }
/* a key with two faces (AC/⌫, the functions under 2nd, Rad/Deg): both are laid out in the same cell, one attribute on
   the keypad shows one of them (keypad.js) — switching repaints a few keys and lays out nothing */
.key > .lbl { grid-area: 1 / 1; }
.lbl-b { opacity: 0; }
.keys[data-typing="true"] [data-face="typing"] .lbl-a, .keys[data-second="true"] [data-face="second"] .lbl-a,
.keys[data-angle="true"] [data-face="angle"] .lbl-a { opacity: 0; }
.keys[data-typing="true"] [data-face="typing"] .lbl-b, .keys[data-second="true"] [data-face="second"] .lbl-b,
.keys[data-angle="true"] [data-face="angle"] .lbl-b { opacity: 1; }
.key.op[aria-pressed="true"] .lbl, .key.sci[aria-pressed="true"] .lbl { font-weight: 600; }
.key:focus { outline: none; }
.key:focus-visible { outline: 2.5px solid var(--white); outline-offset: 3px; box-shadow: 0 0 0 6px rgb(107 71 255 / .55); }

/* ---- 4. the history tape: docked beside the glass on wide screens (a sheet on phones: history.css § 5) ----
   Docked, it takes no room in the layout: app.js (placeTape) works out, once per layout, where it goes beside the
   glass — the glass itself moves aside and shrinks as a transform when the tape opens — so opening it lays out nothing */
.tape { position: absolute; top: 0; left: 0; width: 0; height: 0; }
@media (min-width: 720px) and (min-height: 501px), (min-width: 720px) and (orientation: portrait) {
  /* a blur on a moving canvas would be redone every frame: the studio behind it is smooth, so a little more opaque
     glass looks the same without it */
  .tape .ch-panel { position: fixed; top: var(--tape-y, 0); left: var(--tape-x, 0); width: var(--tape-w, 320px); max-height: var(--ch-dock-h, 70vh);
    -webkit-backdrop-filter: none; backdrop-filter: none; --ch-glass: rgb(255 255 255 / .62); --ch-glass-deep: rgb(255 255 255 / .4); }
}

/* on a phone the tape is a sheet over the glass: a blur there would be redone every frame the liquid moves under it,
   so the sheet is near-opaque glass instead (the scrim already quiets what is behind) */
@media (max-width: 719px), (max-height: 500px) and (orientation: landscape) {
  .tape .ch-panel { -webkit-backdrop-filter: none; backdrop-filter: none; --ch-glass: rgb(250 250 252 / .94); --ch-glass-deep: rgb(244 245 248 / .9); }
}

/* the hidden copy app.js lays out once at idle, so the first switch of layout finds its words already shaped */
.stage.warm { position: fixed; left: -10000px; top: 0; visibility: hidden; pointer-events: none; contain: layout style; }

/* ---- 5. the hint and the toast ---- */
.hint { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--space-3); margin: 0; font: 500 13px var(--font-body); color: var(--on-page-muted);
  letter-spacing: .01em; text-align: center; max-width: 100%; }
.hint-touch { display: none; }
@media (hover: none) and (pointer: coarse) { .hint-pointer { display: none; } .hint-touch { display: inline; } }

.toast { position: fixed; left: 50%; bottom: max(var(--space-5), env(safe-area-inset-bottom)); z-index: 70; padding: 10px 18px; border-radius: var(--radius-pill);
  font: 600 13.5px/1.2 var(--font-body); color: var(--ink-900); background: rgb(255 255 255 / .74);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .8), 0 14px 30px -14px rgb(30 30 60 / .4);
  -webkit-backdrop-filter: blur(18px) saturate(1.5); backdrop-filter: blur(18px) saturate(1.5);
  opacity: 0; visibility: hidden; transform: translate(-50%, 10px); pointer-events: none;
  transition: opacity .18s, transform .25s cubic-bezier(.2, .8, .2, 1), visibility 0s linear .25s; }
.toast.is-on { opacity: 1; visibility: visible; transform: translate(-50%, 0); transition: opacity .18s, transform .25s cubic-bezier(.2, .8, .2, 1), visibility 0s; }

/* ---- 7. screens: the sizes come from --key (app.js); a short landscape screen has no room for the hint ---- */
@media (max-height: 500px) and (orientation: landscape) {
  .stage { gap: 0; padding-top: max(var(--space-2), env(safe-area-inset-top)); padding-bottom: max(var(--space-2), env(safe-area-inset-bottom)); }
  .hint { display: none; }
}

/* ---- 8. when there is no WebGL 2: a frosted slab and frosted keys over a still studio ---- */
.no-gl .gl { display: none; }
.no-gl .fallback-bg { display: block; background: radial-gradient(60% 50% at 50% 40%, var(--studio-50), var(--studio-100) 70%, var(--studio-200)); }
.no-gl .calc { background: linear-gradient(180deg, rgb(255 255 255 / .45), rgb(255 255 255 / .2));
  box-shadow: inset 0 0 0 1.5px rgb(255 255 255 / .8), 0 40px 80px -30px rgb(40 40 60 / .4); overflow: hidden; }
.no-gl .key { background: radial-gradient(120% 120% at 30% 20%, rgb(255 255 255 / .45), rgb(255 255 255 / .1) 60%); box-shadow: inset 0 1px 0 rgb(255 255 255 / .7), inset 0 0 0 1px rgb(255 255 255 / .35); }
.no-gl .liquid2d { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; pointer-events: none; }

/* ---- 9. reduced motion (app.js: no slosh, bubbles, squash or morph) ---- */
@media (prefers-reduced-motion: reduce) {
  .calc { cursor: default; }
  .toast, .tool { transition: none; }
}
