/* Liquid glass calculator — a scientific calculator made of a slab of clear glass standing in a photographer's studio.
   The keys are glass lenses that bend what is behind them; inside the slab a liquid rises with the number and sloshes
   when you press, drag or tilt. The studio, the glass and the liquid are drawn on one canvas (glass.js) in one of
   five tones (classic, crystal, amber, graphite, prism); this file lays out the real HTML on top of it: the display
   and its tool bar, the keys, their labels and focus rings, the history tape's place, the toast.

   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 (.stage[data-layout]: basic 4 × 5, sci-wide 10 × 5, sci-tall 6 × 10). 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   6 the touch circle      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; --umber-900: #2B1E10;
  --graphite-950: #17181B; --graphite-400: #8A8D97; --graphite-100: #E9EAEE;
  --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);
  --hairline: rgb(34 36 44 / .12);
  --surface-quiet: rgb(255 255 255 / .6);
  --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 — white on the dark studio (graphite), graphite on the light ones */
: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 tones (app.js sets html[data-tone]) */
:root[data-tone="classic"], :root[data-tone="crystal"], :root[data-tone="amber"] {
  --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);
}
:root[data-tone="amber"] { --display-ink: var(--umber-900); --label-ink: var(--umber-900); }
:root[data-tone="graphite"] { --page: var(--graphite-950); --on-page-muted: var(--graphite-400); }
:root[data-tone="graphite"] .tilt { color: var(--graphite-100); background: rgb(255 255 255 / .08); }

/* ---- 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%; }
.tool[hidden] { display: none; }
.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); }
  :root[data-tone="graphite"] .tape .ch-panel { --ch-glass: rgb(44 46 54 / .82); --ch-glass-deep: rgb(28 29 34 / .76); }
}

/* 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); }
  :root[data-tone="amber"] .tape .ch-panel { --ch-glass: rgb(255 249 240 / .95); --ch-glass-deep: rgb(255 241 222 / .9); }
  :root[data-tone="graphite"] .tape .ch-panel { --ch-glass: rgb(40 42 50 / .95); --ch-glass-deep: rgb(26 27 32 / .92); }
}

/* 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; } }
.tilt { display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px; border: 0; border-radius: var(--radius-pill); font-size: 13.5px; font-weight: 600;
  color: var(--on-page); background: var(--surface-quiet); box-shadow: inset 0 0 0 1px var(--hairline); cursor: pointer; }
.tilt[aria-pressed="true"] { color: var(--white); background: var(--violet-500); box-shadow: none; }
.tilt[hidden] { display: none; }

.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; }
:root[data-tone="graphite"] .toast { color: var(--graphite-100); background: rgb(40 42 50 / .8); box-shadow: inset 0 0 0 1px rgb(255 255 255 / .12), 0 14px 30px -14px rgb(0 0 0 / .6); }

/* ---- 6. the touch circle, for the video ---- */
.touch { position: fixed; top: 0; left: 0; z-index: 80; width: 44px; height: 44px; margin: -22px 0 0 -22px; border-radius: 50%; pointer-events: none; opacity: 0;
  border: 2px solid var(--white); background: rgb(255 255 255 / .22); box-shadow: 0 0 0 1px rgb(0 0 0 / .35); transition: opacity .12s; will-change: transform; }
.touch.is-on { opacity: 1; }

/* ---- 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)); }
:root[data-tone="graphite"].no-gl .fallback-bg { background: var(--page); }
.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; }
}
