/* ═══════════════════════════════════════════════════════════════════════════
   ATELIER — the front door.

   This is NOT atelier.css. That stylesheet dresses the bahi-khata folio pages
   (/pricing/, /inside-the-app/, /terms/ …) and is left alone; this one dresses
   the one surface whose job is to make a jeweller stop scrolling.

   The world: the showcase tray. A jeweller's own object — velvet field, glass
   over it, one light above. Cream paper is the counter it lies on; every act on
   this page is a tray sliding under that light with the app's answer set on the
   paper beside it. Cream is inherited from the app and is the ground; the
   VELVET is what the page is actually made of, and it carries close to half the
   surface. Gold stays leaf and hairline, never a field.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Substrate — inherited from the app, unchanged */
  --paper:       #F2EBDD;
  --panel:       #FBF6EB;
  --desk:        #E3D9C2;

  /* The velvet. Warm near-black — a neutral black on cream reads as a hole. */
  --velvet:      #17110E;
  --velvet-lift: #241B16;
  --velvet-edge: #3A2C23;

  /* Ink */
  --ink:         #2A211A;
  --ink-deep:    #140F0B;
  --ink-sub:     #6E6048;
  --ink-faint:   #8E8068;

  /* On velvet */
  --on-velvet:      #F0E7D6;
  --on-velvet-sub:  #B7A88E;   /* 6.1:1 on velvet */

  --rule:        #D6C8AC;
  --rule-strong: #BFAE8C;
  --rule-faint:  #E5DBC4;

  --gold:        #C9A95E;
  --gold-light:  #E8D197;
  --gold-text:   #7C5E12;   /* the readable gold, on cream */
  --gold-wash:   #F9EFCF;

  --khata:       #A0452E;

  /* Material tints — the app's signature strip, unchanged */
  --t-gold:      #F8EBC8;
  --t-polki:     #F1DDB2;
  --t-diamond:   #E7ECF4;
  --t-stone:     #E4ECDA;
  --t-labour:    #ECE5D6;

  --cash-text:   #3F5E26;

  /* Fraunces — an old-catalogue serif, warm and slightly wonky on purpose, with
     real weight in its thin strokes. Chosen off /font-lab/ against nine others.
     It replaced Bodoni Moda, which is the trade's own advertising voice but
     whose hairlines genuinely vanish on this cream ground at phone sizes; that
     illegibility is the whole reason this variable exists in its present form.
     NOTE this face is not only the headline — it also draws every rupee figure,
     the rate, the wordmark and the karigar percentages. Changing it changes the
     money. */
  --f-display: "Fraunces", "Bodoni Moda", Georgia, serif;
  --f-sans:    "Inter Tight", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --f-mono:    "DM Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --f-hand:    "Caveat", "Segoe Script", cursive;

  --gutter: clamp(20px, 5vw, 72px);
  --sheet:  1280px;

  --ease:     cubic-bezier(.16, .84, .34, 1);
  --ease-out: cubic-bezier(.22, 1, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: clip;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-sans);
  font-size: 17px;
  line-height: 1.5;
  overflow-x: clip;
  /* The app's own paper grain, so the site and the tool are one substrate. */
  background-image:
    radial-gradient(circle at 20% 12%, rgba(160,130,80,.05), transparent 55%),
    radial-gradient(circle at 82% 78%, rgba(160,130,80,.04), transparent 52%);
}

img { max-width: 100%; display: block; }
a { color: inherit; }

::selection { background: var(--gold-light); color: var(--ink-deep); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink-deep); color: var(--paper);
  padding: 12px 18px; font-size: 14px; font-weight: 600;
}
.skip:focus { left: 12px; top: 12px; }

:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 3px; }

/* ── Type ──────────────────────────────────────────────────────────────── */

.display {
  font-family: var(--f-display);
  font-optical-sizing: auto;
  font-weight: 500;
  line-height: .98;
  letter-spacing: -.018em;   /* Fraunces sets a touch wider than Bodoni did */
  color: var(--ink-deep);
  text-wrap: balance;
}
/* Sized so the thesis and both actions fit the first viewport on a laptop —
   a headline that pushes its own call to action below the fold is a poster,
   not a front door. */
h1.display { font-size: clamp(2.5rem, 4.6vw, 4.05rem); }
h2.display { font-size: clamp(2.1rem, 3.9vw, 3.4rem); }
.display em { font-style: italic; color: var(--gold-text); }
.on-dark .display, .display.on-dark { color: var(--on-velvet); }
.on-dark .display em { color: var(--gold-light); }

/* Ledger notation. The only monospace here, and it is notation — folio marks,
   weights, rates — never a costume for "technical". */
.anno {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-sub);
}
.on-dark .anno, .anno.on-dark { color: var(--on-velvet-sub); }

.lede {
  font-size: clamp(1.05rem, 1.9vw, 1.35rem);
  line-height: 1.5;
  color: var(--ink-sub);
  max-width: 34ch;
  text-wrap: pretty;
}
.on-dark .lede { color: var(--on-velvet-sub); }

/* Every rupee figure is serif with tabular lining figures — the app's own rule,
   and the reason a column of totals reads as a ledger instead of as software. */
.fig {
  font-family: var(--f-display);
  font-weight: 600;
  font-feature-settings: "lnum", "tnum";
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -.01em;
}

/* ── Chrome ────────────────────────────────────────────────────────────── */

.masthead {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  background: rgba(242,235,221,.97);
  border-bottom: 1px solid transparent;
  transition: border-color .3s, background .3s;
}
/* The blur is DESKTOP-ONLY, and that is a performance decision, not a taste one. A
   backdrop-filter on a fixed bar makes the compositor re-read and re-blur the strip of page
   underneath it on every single frame of a scroll. Safari on iOS pays that cost far more
   heavily than Chrome on Android does, which is exactly the shape of the reported fault —
   smooth on one phone, laggy on another, over a 16,000px page. Touch devices get the opaque
   background below instead, which is visually near-identical over this cream ground.
   -webkit- is required: iOS only dropped the prefix in 16.4. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  @media (hover: hover) and (pointer: fine) {
    .masthead {
      -webkit-backdrop-filter: blur(14px) saturate(1.1);
      backdrop-filter: blur(14px) saturate(1.1);
      background: rgba(242,235,221,.72);
    }
    .masthead.stuck { background: rgba(242,235,221,.86); }
  }
}
.masthead.stuck { border-bottom-color: var(--rule); background: rgba(242,235,221,1); }
.masthead-in {
  max-width: var(--sheet); margin: 0 auto;
  padding: 0 var(--gutter);
  height: 68px; display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.wordmark {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-display); font-weight: 600; font-size: 21px;
  letter-spacing: .1em; text-transform: uppercase; text-decoration: none;
  color: var(--ink-deep);
}
.wordmark svg { fill: var(--gold); flex: none; }
.nav { display: flex; align-items: center; gap: 4px; }
.nav a {
  text-decoration: none; font-size: 14.5px; font-weight: 500; color: var(--ink-sub);
  padding: 12px 13px; min-height: 44px; display: inline-flex; align-items: center;
  white-space: nowrap;          /* three items wrapped to three lines each at 390px */
  transition: color .2s;
}
/* A phone gets the two links that lead somewhere it can act on. The detail page
   is reachable from the close and from the footer, twice. */
/* Written as `.nav a.nav-hide`, not `.nav-hide`: `.nav a` above is one point
   more specific, so the bare class loses inside the media query and the link
   stays on screen. */
@media (max-width: 767px) { .nav a.nav-hide { display: none; } }
.nav a:hover { color: var(--ink-deep); }

/* ── Buttons ───────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 52px; padding: 14px 22px;
  font-family: var(--f-sans); font-size: 13.5px; font-weight: 600; letter-spacing: .035em;
  text-transform: uppercase; text-decoration: none;
  border: 1px solid transparent; border-radius: 4px; cursor: pointer;
  transition: transform .12s var(--ease), filter .2s, background .2s, color .2s;
}
.btn:active { transform: scale(.975); }
.btn-gold {
  background: linear-gradient(135deg, #C9A84C, #E8D197 46%, #C9A84C);
  color: #1A0E00; border-color: #B9973F;
}
.btn-ghost { background: transparent; color: var(--ink-deep); border-color: var(--rule-strong); }
.btn-ghost.on-dark { color: var(--on-velvet); border-color: var(--velvet-edge); }
@media (hover: hover) and (pointer: fine) {
  .btn-gold:hover { filter: brightness(1.05); }
  .btn-ghost:hover { background: rgba(42,33,26,.05); border-color: var(--ink-faint); }
  .btn-ghost.on-dark:hover { background: rgba(240,231,214,.07); }
}

/* ── Stage: the sheet the acts are laid out on ─────────────────────────── */

.stage { max-width: var(--sheet); margin: 0 auto; padding: 0 var(--gutter); }

section { position: relative; }

/* ── THE TRAY — the page's one structural object ───────────────────────── */

.tray {
  position: relative;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(255,236,196,.11), transparent 62%),
    linear-gradient(178deg, var(--velvet-lift), var(--velvet) 62%);
  border: 1px solid var(--velvet-edge);
  border-radius: 6px;
  box-shadow:
    0 1px 0 rgba(255,236,196,.10) inset,
    0 30px 70px -34px rgba(60,38,12,.55),
    0 6px 18px -10px rgba(60,38,12,.30);
  overflow: hidden;
  isolation: isolate;
}
/* The velvet's nap: a fine directional weave, not a noise texture. */
.tray::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(97deg, rgba(255,255,255,.016) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(7deg,  rgba(0,0,0,.05) 0 1px, transparent 1px 4px);
  opacity: .8;
}
/* The light above the counter, raking across the tray as it slides in. */
.tray::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(104deg, transparent 30%, rgba(255,240,205,.15) 46%, rgba(255,240,205,.03) 56%, transparent 68%);
  transform: translate3d(-130%, 0, 0);
  transition: transform 1.5s var(--ease-out);
}
.in .tray::after { transform: translate3d(130%, 0, 0); }
.tray > * { position: relative; z-index: 2; }

.tray-pad { padding: clamp(22px, 3.4vw, 40px); }

/* ── Piece card — a piece sitting on the velvet ────────────────────────── */

.piece { position: relative; }
.piece-shot {
  position: relative; aspect-ratio: 1 / 1; overflow: hidden; border-radius: 4px;
  background: #100C0A;
  border: 1px solid rgba(201,169,94,.22);
}
.piece-shot img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.1s var(--ease-out);
}
.piece-name {
  margin-top: 12px; font-size: 13.5px; font-weight: 500; color: var(--on-velvet);
  line-height: 1.35; letter-spacing: .01em;
}
.piece-meta { margin-top: 3px; font-size: 11px; color: var(--on-velvet-sub); font-family: var(--f-mono); letter-spacing: .06em; }
.piece-price {
  margin-top: 9px; font-size: clamp(1.25rem, 2.1vw, 1.7rem); color: var(--gold-light);
  transition: color .5s;
}
.piece-price.moved { color: #FFF0C8; }

/* The material strip: the app's signature. Never a hairline bar — it needs
   height and a rule between segments or the five tints read as one beige line. */
.strip { display: flex; height: 9px; margin-top: 11px; border: 1px solid rgba(201,169,94,.3); border-radius: 2px; overflow: hidden; }
.strip i { display: block; height: 100%; }
.strip i + i { border-left: 1px solid rgba(23,17,14,.5); }
.s-gold   { background: var(--t-gold); }
.s-polki  { background: var(--t-polki); }
.s-diamond{ background: var(--t-diamond); }
.s-stone  { background: var(--t-stone); }
.s-labour { background: var(--t-labour); }

/* ── Act layout ────────────────────────────────────────────────────────── */

.act { padding: clamp(58px, 8.5vh, 104px) 0; }
/* No measure cap on the block itself. It used to carry `max-width: 44ch`, which
   is 44 zeros of INTER TIGHT AT 17px — about 432px — and that, not the heading's
   own cap, was what governed the headlines. Under Bodoni (a narrow face) they
   just fit; under Fraunces every one of them broke, "Photograph the paper."
   splitting across two lines with an orphan beneath it. The lede carries its own
   34ch measure, so the block never needed one. Measured, not guessed: the
   longest line here ("One of them costs you more gold.") needs 776px at
   3.4rem — the 24ch below leaves room for it. */
.act-head { margin-bottom: clamp(24px, 3vw, 38px); }
.act-head .lede { max-width: 44ch; }
/* The anno is one short label and must not wrap: at 44ch the longest of them,
   "The customer who saw it somewhere else", broke and left "ELSE" on its own
   line above the headline. */
.act-head .anno { max-width: 62ch; }
.act-head h2 { max-width: 24ch; }
.act-head .anno { display: block; margin-bottom: 18px; }
.act-head .lede { margin-top: 20px; }

.split {
  display: grid; gap: clamp(26px, 4vw, 56px);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 768px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split.wide-right { grid-template-columns: .95fr 1.05fr; }
  .split.wide-left  { grid-template-columns: 1.18fr .82fr; }
}

/* ── HERO ──────────────────────────────────────────────────────────────── */

.hero { padding-top: calc(68px + clamp(26px, 4.5vh, 56px)); padding-bottom: clamp(52px, 8vh, 96px); }
.hero h1 { margin-top: 20px; max-width: 15ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
.hero-note { margin-top: 26px; font-size: 14px; color: var(--ink-sub); max-width: 40ch; }
.hero-note strong { color: var(--ink-deep); font-weight: 600; }

/* The rate of the day — the one number the whole product hangs off.
   The min-height is load-bearing, not cosmetic: the Live readout and the Manual
   editor swap in and out of this one slot, and without a floor the whole page
   below the hero jumped every time the switch was thrown. Both are sized off
   the same clamp for the same reason. */
.rate-block {
  display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap;
  min-height: clamp(2.6rem, 6.4vw, 4.6rem);
}
.rate-fig {
  font-family: var(--f-display); font-weight: 600;
  font-variant-numeric: tabular-nums lining-nums;
  font-size: clamp(2.6rem, 6.4vw, 4.6rem); line-height: 1;
  color: var(--ink-deep); letter-spacing: -.02em;
}
.rate-unit { font-size: 12px; font-family: var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-sub); padding-bottom: 10px; }
.rate-delta {
  font-family: var(--f-mono); font-size: 12.5px; letter-spacing: .04em;
  color: var(--cash-text); padding-bottom: 11px; opacity: 0; transition: opacity .4s;
}
.rate-delta.on { opacity: 1; }

/* Manual → Live. The switch is the demonstration, so it is drawn at a size
   that can be read from across a room, not as a settings-row toggle. */
.switch { display: inline-flex; align-items: center; gap: 14px; margin-top: 26px; }
.switch-track {
  position: relative; width: 92px; height: 40px; border-radius: 999px;
  background: var(--desk); border: 1px solid var(--rule-strong);
  transition: background .5s var(--ease), border-color .5s;
  flex: none;
}
.switch-knob {
  position: absolute; top: 3px; left: 3px; width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(140deg, #FBF6EB, #E3D9C2);
  border: 1px solid var(--rule-strong);
  box-shadow: 0 2px 6px rgba(80,55,20,.22);
  transition: transform .62s var(--ease), background .5s, border-color .5s;
}
.switch.live .switch-track { background: var(--gold-wash); border-color: var(--gold); }
.switch.live .switch-knob {
  transform: translateX(52px);
  background: linear-gradient(140deg, #E8D197, #C9A84C);
  border-color: #B9973F;
}
.switch-label { font-family: var(--f-mono); font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-sub); transition: color .4s; }
.switch.live .switch-label { color: var(--gold-text); }
.live-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--cash-text);
  margin-right: 7px; opacity: 0; transform: scale(.4); transition: opacity .4s, transform .4s;
}
.switch.live .live-dot { opacity: 1; transform: scale(1); animation: pulse 2.4s var(--ease) infinite; }
@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: .3 } }

.hero-tray { padding: clamp(18px, 2.4vw, 26px); }
.hero-pieces { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(10px, 1.6vw, 18px); }
.hero-tray .piece-name { font-size: 12.5px; }
.hero-tray .piece-price { font-size: clamp(1rem, 1.7vw, 1.35rem); }

@media (max-width: 767px) {
  .hero-pieces { grid-template-columns: 1fr 1fr; }
  .hero-pieces .piece:nth-child(3) { display: none; }
  /* Act 2's tray reuses .hero-pieces but must keep all three: the film counts
     the pieces in aloud ("3 pieces"), so dropping one would make the count lie. */
  .scene-capture .hero-pieces { grid-template-columns: repeat(3, 1fr); }
  .scene-capture .hero-pieces .piece:nth-child(3) { display: block; }
}

/* ── Demonstration furniture, shared by the acts ───────────────────────── */

.slip {                     /* the paper that arrives from the real world */
  background: linear-gradient(178deg, #FDFBF3, #F4EEDE);
  border: 1px solid var(--rule); border-radius: 3px;
  padding: 20px 22px;
  box-shadow: 0 14px 30px -18px rgba(60,38,12,.4);
  position: relative; overflow: hidden;
}
.slip-hand { font-family: var(--f-hand); font-size: 21px; line-height: 1.85; color: #2C3E63; }
.slip-rule { height: 1px; background: var(--rule-faint); margin: 9px 0; }

.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; min-height: 44px; padding: 8px 16px;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  font-family: var(--f-sans);
  font-size: 12.5px; font-weight: 600; letter-spacing: .04em;
  color: var(--ink-sub); background: transparent; cursor: pointer;
  transition: background .45s var(--ease), color .45s, border-color .45s, transform .3s;
}
.chip:active { transform: scale(.96); }
.chip.on { background: var(--gold-wash); color: var(--gold-text); border-color: var(--gold); }
.chip.on-dark { border-color: var(--velvet-edge); color: var(--on-velvet-sub); }
.chip.on-dark.on { background: rgba(201,169,94,.18); color: var(--gold-light); border-color: var(--gold); }

.readout { border-top: 1px solid var(--rule); padding-top: 18px; margin-top: 18px; }
.readout-row { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 7px 0; }
.readout-row + .readout-row { border-top: 1px solid var(--rule-faint); }
.readout-k { font-size: 13.5px; color: var(--ink-sub); }
.readout-v { font-size: 16px; }
.readout-tot { border-top: 1px solid var(--rule-strong); margin-top: 6px; padding-top: 14px; }
.readout-tot .readout-k { color: var(--ink-deep); font-weight: 600; }
.readout-tot .readout-v { font-size: clamp(1.4rem, 2.6vw, 1.9rem); }

.verdict {
  margin-top: 18px; padding: 15px 18px; border-radius: 4px;
  background: #E6EEDB; border: 1px solid #9AAE7D;
  font-size: 15px; color: var(--cash-text); font-weight: 500;
}
.verdict .fig { font-size: 1.15em; }

/* ── Catalogue grid ────────────────────────────────────────────────────── */

.cat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(8px, 1.4vw, 14px); max-width: 820px; margin: 0 auto; }
@media (max-width: 767px) { .cat-grid { grid-template-columns: repeat(2, 1fr); } }
.cat-cell {
  transition: opacity .55s var(--ease), transform .55s var(--ease), filter .55s;
}
.cat-cell.out { opacity: .3; filter: saturate(.5); transform: scale(.94); }

/* ── Dead stock ────────────────────────────────────────────────────────── */

.age-bar { height: 4px; background: rgba(240,231,214,.14); border-radius: 2px; overflow: hidden; margin-top: 10px; }
.age-fill {
  display: block; height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--gold), #C68874);
  /* scaleX, not width: animating width relayouts the row on every frame.
     `--age` is the bar's own full length, carried inline in the markup; the
     film beat scales it. With no film running, --f-a* is undefined, the whole
     declaration is invalid and the bar renders full — its finished frame. */
  transform-origin: left center;
}
[data-dead="0"] .age-fill { transform: scaleX(calc(var(--age) * var(--f-a0))); }
[data-dead="1"] .age-fill { transform: scaleX(calc(var(--age) * var(--f-a1))); }
[data-dead="2"] .age-fill { transform: scaleX(calc(var(--age) * var(--f-a2))); }
.age-days { font-family: var(--f-mono); font-size: 11px; letter-spacing: .08em; color: #C68874; margin-top: 8px; }
.stamp {
  position: absolute; top: 14px; left: 14px; z-index: 4;
  font-family: var(--f-mono); font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  color: #F4DCD2; border: 1.5px solid #C68874; border-radius: 3px;
  padding: 6px 10px; background: rgba(155,59,32,.35);
  opacity: var(--f-stamp);
  transform: rotate(-7deg) scale(calc(1.5 - .5 * var(--f-stamp)));
}

/* ── Karigar bars ──────────────────────────────────────────────────────── */

.bars { display: grid; gap: 20px; }
.bar-row { display: grid; grid-template-columns: 1fr; gap: 8px; }
.bar-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.bar-name { font-size: 15px; color: var(--on-velvet); font-weight: 500; }
.bar-val { font-family: var(--f-display); font-weight: 600; font-variant-numeric: tabular-nums; font-size: 17px; color: var(--on-velvet-sub); }
.bar-row.worst .bar-val { color: #E0A48C; }
.bar-track { height: 13px; background: rgba(20,15,11,.55); border: 1px solid rgba(240,231,214,.11); border-radius: 2px; overflow: hidden; }
.bar-fill {
  /* display:block is load-bearing: these fills are <i> elements, and width has
     no effect on an inline box — the bars rendered as empty tracks. */
  display: block;
  height: 100%; width: 100%; border-radius: 1px;
  background: var(--gold);
  box-shadow: 0 1px 0 rgba(255,240,205,.35) inset;
  transform-origin: left center;
}
[data-kar="0"] .bar-fill { transform: scaleX(calc(var(--bar) * var(--f-b0))); }
[data-kar="1"] .bar-fill { transform: scaleX(calc(var(--bar) * var(--f-b1))); }
[data-kar="2"] .bar-fill { transform: scaleX(calc(var(--bar) * var(--f-b2))); }
[data-kar="3"] .bar-fill { transform: scaleX(calc(var(--bar) * var(--f-b3))); }
.bar-row.worst .bar-fill { background: #C68874; }
.kar-verdict {
  margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--velvet-edge);
  font-size: 15px; line-height: 1.6; color: var(--on-velvet-sub); max-width: 62ch;
  opacity: var(--f-verd);
}
.kar-verdict b { color: var(--on-velvet); font-weight: 600; }
.kar-verdict b.fig { color: var(--gold-light); }

/* ═══════════════════════════════════════════════════════════════════════════
   THE FILM SYSTEM

   A film section carries a tall .film-rail; inside it .film-stage is pinned to
   the viewport. home.js turns scroll position into a set of beat variables
   (--f-slip, --f-scan, --f-c0 …), each a bare number from 0 to 1, and every
   rule below reads one of them. Nothing here is an @keyframes and nothing has
   a duration: the visitor's scroll IS the timeline, which is what makes every
   film rewind for free.

   THE FAILSAFE IS THE CASCADE ITSELF, not a fallback value. The beat variables
   are never declared in CSS — only home.js ever sets them. An undeclared
   custom property makes its whole declaration invalid at computed-value time,
   so `opacity: var(--f-c0)` computes to the initial value 1 and
   `transform: …var(--f-c0)…` computes to none. A film with no script running
   therefore paints its FINISHED frame, every card present and every bar full.
   Do not add fallbacks like var(--f-c0, 0) — that would invert this and hide
   the content of every film the moment the script failed.

   The rails only get their height, and the stages only get pinned, under
   html.html-js — the class the head's dead man's switch removes — so a dead
   script leaves no empty scroll behind either.
   ═══════════════════════════════════════════════════════════════════════════ */

.film-rail { position: relative; }
.html-js .film-rail { height: calc(100vh + 190vh); height: calc(100svh + 190vh); }

.film-stage { position: relative; }
.html-js .film-stage {
  position: sticky; top: 0;
  height: 100vh; height: 100svh;
  display: flex; align-items: center;
  padding-top: 68px;              /* clear the fixed masthead */
  overflow: hidden;
}
.film-stage > .stage { width: 100%; }

/* A pinned stage is exactly one screen tall and clips, so on a short phone the
   taller scenes lost their bottom rows — measured at 375x666 the quote scene
   overran by 173px, which is the total and the share button, i.e. the end of
   the film. Rather than cut the scenes down for every device, home.js measures
   each one against the stage it has to live in and sets --fit; the scene is
   scaled to that. Undefined (no script) makes this declaration invalid and the
   transform resolves to none, which is correct — an unpinned scene has the
   whole page to be tall in. */
.scene { transform: scale(var(--fit)); transform-origin: center center; }

/* The one element on the page that is hidden by default and revealed by the
   script, and deliberately the opposite way round from everything else: it is
   an INSTRUCTION, not content. With no script the films are finished stills,
   and telling a reader to scroll through a film that is not running would be
   the only actively false thing on the page. */
.film-cue { display: none; }
.html-js .film-cue {
  display: block; text-align: center; margin-bottom: 18px;
  opacity: calc(var(--f-cue) * .75);
}
@media (max-width: 767px) { .film-cue { margin-bottom: 12px; } }

/* ── ACT 2 scene — the paper, the phone, the shelf ─────────────────────── */

.scene-capture { display: grid; gap: clamp(20px, 3.4vw, 48px); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .scene-capture { grid-template-columns: .82fr 1.18fr; } }

.cap-left { display: flex; justify-content: center; }
.cap-phone { position: relative; width: min(100%, 330px); }

/* The phone that comes down over the paper. Drawn as a frame BEHIND the slip
   rather than a box around it, so the paper can be on the counter first and
   the phone can arrive over it without the paper ever moving. */
.cap-phone::before {
  content: ""; position: absolute; inset: -16px -13px -40px; z-index: 0;
  border-radius: 30px; background: #1B1512;
  border: 1px solid #3A2C23;
  box-shadow: 0 34px 70px -26px rgba(40,24,8,.55), 0 0 0 1px rgba(255,236,196,.05) inset;
  opacity: var(--f-phone);
  transform: scale(calc(1.05 - .05 * var(--f-phone)));
}
/* The chin's home indicator — the one detail that stops the frame reading as
   a picture frame instead of a phone. */
.cap-phone::after {
  content: ""; position: absolute; z-index: 2;
  left: 50%; bottom: -25px; width: 84px; height: 4px; margin-left: -42px;
  border-radius: 999px; background: rgba(240,231,214,.32);
  opacity: var(--f-phone);
}

.cap-phone-body { position: relative; z-index: 1; overflow: hidden; border-radius: 4px; }
.cap-slip {
  box-shadow: none;
  opacity: var(--f-slip);
  transform: translate3d(0, calc((1 - var(--f-slip)) * 22px), 0);
}
/* Grid rather than flowing text: every line is a fixed row, so a line swapping
   its handwriting for a parsed field cannot change the height of the paper. */
.cap-slip .slip-hand { display: grid; gap: 15px; font-size: 17px; line-height: 1.7; }

/* The handwriting and the parsed field occupy ONE grid cell and cross-fade, so
   neither can push the other around and the line never changes height. */
.cap-line { display: grid; position: relative; }
.cap-line > * { grid-area: 1 / 1; align-self: center; font-style: normal; }
.cap-raw { font-family: var(--f-hand); color: #2C3E63; }
/* Hidden by default, unlike everything else on this page — the two halves of a
   line are stacked, so leaving both visible in the no-script fallback would
   print the parsed field ON TOP of the handwriting. With no script the paper
   simply reads as paper, which is the honest still. */
.cap-chip { display: none; }
.html-js .cap-chip {
  display: flex; align-items: baseline; gap: 8px;
  font-family: var(--f-mono);
  font-size: 10.5px; letter-spacing: .06em;
  color: var(--ink-sub);
}
.cap-chip b {
  font-weight: 500; font-size: 9px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--gold-text); background: var(--gold-wash);
  border: 1px solid var(--gold); border-radius: 2px; padding: 2px 6px;
  white-space: nowrap;
}
/* A gold rule draws under the line as it is understood. */
.cap-line::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 1px; height: 1px;
  background: var(--gold); transform-origin: left center;
}
[data-line="0"]::after { transform: scaleX(var(--f-l0)); }
[data-line="1"]::after { transform: scaleX(var(--f-l1)); }
[data-line="2"]::after { transform: scaleX(var(--f-l2)); }
[data-line="3"]::after { transform: scaleX(var(--f-l3)); }
[data-line="4"]::after { transform: scaleX(var(--f-l4)); }
[data-line="0"] .cap-raw { opacity: calc(1 - var(--f-l0)); } [data-line="0"] .cap-chip { opacity: var(--f-l0); }
[data-line="1"] .cap-raw { opacity: calc(1 - var(--f-l1)); } [data-line="1"] .cap-chip { opacity: var(--f-l1); }
[data-line="2"] .cap-raw { opacity: calc(1 - var(--f-l2)); } [data-line="2"] .cap-chip { opacity: var(--f-l2); }
[data-line="3"] .cap-raw { opacity: calc(1 - var(--f-l3)); } [data-line="3"] .cap-chip { opacity: var(--f-l3); }
[data-line="4"] .cap-raw { opacity: calc(1 - var(--f-l4)); } [data-line="4"] .cap-chip { opacity: var(--f-l4); }

.cap-scan {
  position: absolute; left: 0; right: 0; top: 0; height: 34%; z-index: 3; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(201,169,94,.30), transparent);
  border-bottom: 1px solid rgba(201,169,94,.8);
  transform: translateY(calc(var(--f-scan) * 300%));
  /* A trapezoid: solid through the middle of the pass, faded at both ends, so
     the light does not pop into existence or vanish at the paper's edge. */
  opacity: calc(min(var(--f-scan) * 6, (1 - var(--f-scan)) * 6, 1));
}
.cap-flash {
  position: absolute; inset: 0; z-index: 4; pointer-events: none;
  background: #FFFDF4; opacity: calc(var(--f-flash) * .82);
}
/* Viewfinder brackets — the frame the camera puts on the thing it is reading. */
.cap-vf {
  position: absolute; z-index: 5; width: 22px; height: 22px; pointer-events: none;
  border: 2px solid var(--gold-light);
  opacity: calc(var(--f-vf) * (1 - var(--f-scan)));
}
.cap-vf-tl { top: -7px; left: -7px;  border-right: 0; border-bottom: 0; }
.cap-vf-tr { top: -7px; right: -7px; border-left: 0;  border-bottom: 0; }
.cap-vf-bl { bottom: -7px; left: -7px;  border-right: 0; border-top: 0; }
.cap-vf-br { bottom: -7px; right: -7px; border-left: 0;  border-top: 0; }
.cap-shutter { display: none; }

/* Where the pieces land */
.cap-card { opacity: var(--f-c0); }
[data-cap-card="0"] { opacity: var(--f-c0); transform: translate3d(calc((1 - var(--f-c0)) * -30px), 0, 0) scale(calc(.93 + .07 * var(--f-c0))); }
[data-cap-card="1"] { opacity: var(--f-c1); transform: translate3d(calc((1 - var(--f-c1)) * -30px), 0, 0) scale(calc(.93 + .07 * var(--f-c1))); }
[data-cap-card="2"] { opacity: var(--f-c2); transform: translate3d(calc((1 - var(--f-c2)) * -30px), 0, 0) scale(calc(.93 + .07 * var(--f-c2))); }

@media (max-width: 899px) {
  .cap-phone { width: min(100%, 250px); }
  .cap-slip .slip-hand { font-size: 14px; line-height: 2.3; }
  .cap-chip { font-size: 8px; padding: 1px 6px; }
  .scene-capture .hero-pieces { grid-template-columns: repeat(3, 1fr); }
  .scene-capture .piece-name { font-size: 11px; }
  .scene-capture .piece-meta { display: none; }
  .scene-capture .piece-price { font-size: .95rem; }
}

/* ── ACT 3 scene — her message, your rates ─────────────────────────────── */

.scene-quote { display: grid; gap: clamp(20px, 3.4vw, 48px); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .scene-quote { grid-template-columns: 1fr 1fr; } }

.chat { margin-bottom: 16px; opacity: var(--f-msg); transform: translate3d(0, calc((1 - var(--f-msg)) * 14px), 0); }
.chat-bubble {
  position: relative; display: inline-block; max-width: 30ch;
  background: #E9F3DC; border: 1px solid #C4D9A9; border-radius: 12px 12px 12px 3px;
  padding: 11px 14px 8px; font-size: 14px; color: #26331A; line-height: 1.5;
}
.chat-name { display: block; font-size: 11.5px; font-weight: 700; color: #4B7A26; margin-bottom: 4px; }
.chat-link { display: block; font-size: 12.5px; color: #2F6ABF; word-break: break-all; margin-bottom: 5px; }
.chat-time { display: block; text-align: right; font-size: 10px; color: #7C8C6B; margin-top: 4px; }

.q-slip { opacity: var(--f-slip); transform: translate3d(0, calc((1 - var(--f-slip)) * 18px), 0); }

/* The tenant's own rate table — the thing that makes the answer HERS. */
.mother {
  background: var(--panel); border: 1px solid var(--rule); border-radius: 4px;
  padding: 16px 18px; margin-bottom: 18px;
  opacity: var(--f-mother); transform: translate3d(0, calc((1 - var(--f-mother)) * 16px), 0);
}
.mother .anno { display: block; margin-bottom: 10px; }
.mother-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 6px 0; font-size: 13.5px; color: var(--ink-sub);
}
.mother-row + .mother-row { border-top: 1px dashed var(--rule-faint); }
.mother-row .fig { font-size: 14px; color: var(--ink-deep); }
[data-mrate="0"] { opacity: var(--f-m0); }
[data-mrate="1"] { opacity: var(--f-m1); }
[data-mrate="2"] { opacity: var(--f-m2); }

[data-qrow="0"] { opacity: var(--f-q0); transform: translate3d(calc((1 - var(--f-q0)) * 12px), 0, 0); }
[data-qrow="1"] { opacity: var(--f-q1); transform: translate3d(calc((1 - var(--f-q1)) * 12px), 0, 0); }
[data-qrow="2"] { opacity: var(--f-q2); transform: translate3d(calc((1 - var(--f-q2)) * 12px), 0, 0); }
[data-qrow="3"] { opacity: var(--f-q3); transform: translate3d(calc((1 - var(--f-q3)) * 12px), 0, 0); }
[data-qverdict]  { opacity: var(--f-verd); transform: scale(calc(.97 + .03 * var(--f-verd))); }
[data-qsend] {
  margin-top: 20px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  opacity: var(--f-send); transform: translate3d(0, calc((1 - var(--f-send)) * 12px), 0);
}
.q-send-note { font-size: 12.5px; color: var(--ink-faint); }

@media (max-width: 899px) {
  .scene-quote .chat { margin-bottom: 10px; }
  .scene-quote .q-slip { display: none; }   /* the bubble already says what she sent */
  .mother { padding: 12px 14px; margin-bottom: 12px; }
  .mother-row { font-size: 12.5px; padding: 4px 0; }
  .readout { padding-top: 12px; margin-top: 12px; }
  .readout-row { padding: 4px 0; }
}

/* ── The WhatsApp action ───────────────────────────────────────────────── */

.btn-wa { background: #1FA855; color: #FFF; border-color: #17944A; }
.btn-wa:disabled { opacity: .45; cursor: not-allowed; }
@media (hover: hover) and (pointer: fine) { .btn-wa:not(:disabled):hover { filter: brightness(1.08); } }

/* ── ACT 4 extras — the catalogue is a control, not a picture ──────────── */

.chip-head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin-bottom: 12px;
}
.chip-reset {
  background: transparent; border: 1px solid var(--velvet-edge); border-radius: 999px;
  color: var(--on-velvet-sub); font-family: var(--f-sans); font-size: 11.5px;
  font-weight: 600; letter-spacing: .06em; padding: 6px 13px; cursor: pointer;
  transition: color .2s, border-color .2s;
}
.chip-reset:hover { color: var(--on-velvet); border-color: var(--gold); }
.cat-grid { margin-top: 22px; }
.cat-cell.out { pointer-events: none; }
.cat-empty {
  text-align: center; color: var(--on-velvet-sub); font-size: 14px;
  padding: 30px 0 6px;
}
.cat-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; margin-top: 24px;
}

/* ── ACT 5 scene — ageing, then the decision ───────────────────────────── */

.dead-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px, 2vw, 22px); }
/* The three cards used to sit on their own baselines because the names run to
   different line counts, so the bars and the day counts stepped down the row.
   Column layout with the name given a fixed measure aligns every rule. */
.dead-piece { display: flex; flex-direction: column; }
.dead-piece .piece-name { min-height: 2.7em; }
.dead-piece .age-bar { margin-top: auto; }
[data-dead="0"] { opacity: var(--f-d0); }
[data-dead="1"] { opacity: var(--f-d1); }
[data-dead="2"] { opacity: var(--f-d2); }

.calls {
  margin-top: clamp(20px, 3vw, 32px); padding-top: 20px;
  border-top: 1px solid var(--velvet-edge);
  opacity: var(--f-calls); transform: translate3d(0, calc((1 - var(--f-calls)) * 14px), 0);
}
.calls-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.calls-money { display: flex; gap: clamp(16px, 3vw, 34px); flex-wrap: wrap; }
.calls-money > span { display: flex; flex-direction: column; gap: 4px; }
.calls-money i { font-style: normal; }
.calls-money b { font-weight: 600; font-size: clamp(1rem, 1.7vw, 1.3rem); color: var(--gold-light); }
.calls-row { display: flex; gap: 9px; flex-wrap: wrap; margin-top: 18px; }
.call {
  display: inline-flex; align-items: center; min-height: 40px; padding: 8px 16px;
  border: 1px solid var(--velvet-edge); border-radius: 999px;
  font-size: 12.5px; font-weight: 600; letter-spacing: .04em; color: var(--on-velvet-sub);
}
[data-call="0"] { opacity: var(--f-k0); }
[data-call="1"] { opacity: var(--f-k1); }
[data-call="2"] { opacity: var(--f-k2); }
[data-call="3"] { opacity: var(--f-k3); }
/* The owner's decision, landing last. It is the only judgement the app ever
   stores against a piece, so it is the beat the film ends on. */
.call-pick {
  border-color: color-mix(in srgb, #C68874 calc(var(--f-pick) * 100%), var(--velvet-edge));
  background: rgba(198,136,116, calc(var(--f-pick) * .22));
  color: color-mix(in srgb, #F4DCD2 calc(var(--f-pick) * 100%), var(--on-velvet-sub));
}

@media (max-width: 767px) {
  .dead-row { grid-template-columns: repeat(3, 1fr); }
  .scene-dead .piece-name { font-size: 11px; min-height: 3.6em; }
  .scene-dead .age-days { font-size: 9.5px; }
  .calls-row { gap: 6px; }
  .call { font-size: 11px; padding: 6px 11px; min-height: 34px; }
}

/* ── ACT 1 — the rate box in Manual ────────────────────────────────────── */

.rate-controls { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 22px; }
.switch {
  background: transparent; border: 0; padding: 0; margin-top: 0; cursor: pointer;
  font: inherit; color: inherit;
}
/* An instruction, so it follows the .film-cue rule rather than the page's: with
   no script the switch does not switch, and inviting a tap on it would be a
   promise the page could not keep. */
.rate-hint { display: none; }
.html-js .rate-hint { display: block; font-size: 12.5px; color: var(--ink-faint); max-width: 34ch; line-height: 1.45; }

/* Sized to sit in the same slot as .rate-fig, because in Manual it IS the
   rate — not a settings box next to a headline number saying the same thing. */
.rate-manual { display: inline-flex; align-items: center; gap: 10px; }
.rate-manual[hidden] { display: none; }
.rate-input-wrap {
  display: inline-flex; align-items: baseline; gap: 2px;
  border-bottom: 2px solid var(--gold);
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(2.6rem, 6.4vw, 4.6rem); line-height: 1;   /* == .rate-fig */
  color: var(--ink-deep); letter-spacing: -.02em;
}
.rate-manual input {
  width: 5.2ch; padding: 0; border: 0; background: transparent;
  font: inherit; color: inherit; letter-spacing: inherit;
  font-variant-numeric: tabular-nums lining-nums;
  -moz-appearance: textfield;
}
.rate-manual input:focus { outline: none; }
.rate-input-wrap:focus-within { border-bottom-color: var(--ink-deep); }
.rate-step {
  flex: none; width: 42px; height: 42px; border-radius: 50%;
  border: 1px solid var(--rule-strong); background: var(--panel);
  font-family: var(--f-sans); font-size: 20px; line-height: 1; color: var(--ink-sub);
  cursor: pointer; transition: background .2s, border-color .2s, color .2s;
}
.rate-step:hover { border-color: var(--gold); color: var(--ink-deep); background: var(--gold-wash); }
.rate-step:active { transform: scale(.94); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ═══ FORMS (the /try/ sign-up) ══════════════════════════════════════════════
   One shared field style for the site's few real forms. Paper input on the
   cream ground, on the front page's tighter 2-6px radius ladder rather than
   the app's 8-20px one — a form on a marketing page is not app chrome. */
.form { max-width: 420px; }
.field { margin-top: 16px; }
.field label {
  display: block; font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--on-velvet-sub); margin-bottom: 6px;
}
.field input {
  width: 100%; box-sizing: border-box; padding: 12px 14px; font-size: 16px;
  font-family: var(--f-sans); color: var(--ink); background: var(--panel);
  border: 1px solid var(--rule); border-radius: 4px; transition: border-color .2s;
}
.field input:focus { outline: none; border-color: var(--gold); }
.form-actions { margin-top: 20px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.form-note { font-size: 12.5px; color: var(--on-velvet-sub); line-height: 1.5; margin-top: 10px; }
/* --khata is otherwise unused on this stylesheet (see DESIGN.md) — this is its one legitimate
   job here: a form validation error is a genuinely new need this palette didn't have before. */
.form-error {
  margin-top: 14px; padding: 10px 14px; border-radius: 4px; font-size: 13px;
  background: color-mix(in srgb, var(--khata) 14%, var(--velvet)); color: var(--khata);
  display: none;
}
.form-error.show { display: block; }
.form[data-busy] .form-actions button { opacity: .6; pointer-events: none; }

/* The credentials shown after a successful /try/ sign-up — same paper-input treatment as .field
   input, but read-only rows with a copy button since these get typed into the Log In screen
   later, on a different device, not right now. */
.demo-success[hidden] { display: none; }
.demo-creds { max-width: 420px; display: flex; flex-direction: column; gap: 8px; }
.demo-cred-row {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  background: var(--panel); border: 1px solid var(--rule); border-radius: 4px;
}
.demo-cred-row span {
  flex: none; width: 66px; font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-sub);
}
/* Specificity fight with .band-ink strong (color: var(--on-velvet), a light-on-dark tone) — that
   rule targets every <strong> in this dark section, including these, which sit on the LIGHT
   paper box below, not the dark velvet ground. Same (0,1,1) specificity, so .band-ink strong wins
   on source order alone unless matched with an extra ancestor class here. */
.demo-success .demo-cred-row strong {
  flex: 1; font-family: var(--f-mono); font-size: 13px; font-weight: 500; color: var(--ink-deep);
  overflow-wrap: anywhere;
}
.demo-cred-copy {
  flex: none; font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--gold); background: none; border: 1px solid var(--rule);
  border-radius: 4px; padding: 5px 10px; cursor: pointer; transition: border-color .2s;
}
.demo-cred-copy:hover { border-color: var(--gold); }

/* ═══ THE SHARE SHEET ═══════════════════════════════════════════════════════
   Both panels are hand-rebuilt from the app's own renderers — the quote card
   from QuoteCardSideBySide (its default style) and the catalogue page from
   CatalogPrintPage. Type, colour and proportion are copied from those
   components, including their Jost/Cormorant stack, so what a visitor is shown
   here is what the product actually puts into the chat.
   ═══════════════════════════════════════════════════════════════════════════ */

body.sheet-open { overflow: hidden; }

.sheet-wrap { position: fixed; inset: 0; z-index: 90; display: flex; align-items: center; justify-content: center; padding: clamp(12px, 3vw, 34px); }
.sheet-wrap[hidden] { display: none; }
.sheet-back { position: absolute; inset: 0; background: rgba(20,15,11,.62); opacity: 0; transition: opacity .26s var(--ease); }
.sheet-wrap.in .sheet-back { opacity: 1; }
.sheet-panel {
  position: relative; z-index: 1;
  width: min(560px, 100%); max-height: 100%;
  display: flex; flex-direction: column;
  background: var(--paper); border: 1px solid var(--rule); border-radius: 6px;
  box-shadow: 0 40px 90px -30px rgba(20,15,11,.6);
  opacity: 0; transform: translate3d(0, 18px, 0) scale(.98);
  transition: opacity .26s var(--ease), transform .3s var(--ease);
}
.sheet-wrap.in .sheet-panel { opacity: 1; transform: none; }
.sheet-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px 16px 12px; border-bottom: 1px solid var(--rule); flex: none;
}
.sheet-x {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--rule); background: transparent;
  font-size: 22px; line-height: 1; color: var(--ink-sub); cursor: pointer;
}
.sheet-x:hover { border-color: var(--ink-faint); color: var(--ink-deep); }
.sheet-body { overflow: auto; padding: clamp(14px, 3vw, 24px); -webkit-overflow-scrolling: touch; }
.sheet-foot {
  flex: none; padding: 12px 16px 15px; border-top: 1px solid var(--rule);
  font-size: 12.5px; line-height: 1.5; color: var(--ink-faint);
}

/* The chat the picture is dropped into — one grain of context, so the card is
   seen at the size a customer actually sees it. */
.wa-chat { background: #E5DDD3; border-radius: 8px; padding: 12px; }
.wa-tick { text-align: right; font-size: 10.5px; color: #7C8C6B; margin-top: 6px; }

/* ── The quote card, as QuoteCardSideBySide draws it ───────────────────── */
.qc { width: 100%; max-width: 420px; margin: 0 auto; background: #FAFAF6; color: #1C1713; font-family: "Jost", var(--f-sans); }
.qc-bar { display: block; height: 6px; background: linear-gradient(90deg, #C9A84C, #E8D197, #C9A84C); }
.qc-bar-b { height: 5px; }
.qc-top { display: flex; padding: 22px; gap: 18px; align-items: center; }
.qc-shot { width: 130px; height: 130px; flex: none; overflow: hidden; }
.qc-shot img { width: 100%; height: 100%; object-fit: cover; }
.qc-headings { flex: 1; min-width: 0; }
.qc-kicker { font-weight: 500; font-size: 10px; letter-spacing: 3px; text-transform: uppercase; color: #B8973A; }
.qc-name { font-family: "Cormorant Garamond", Georgia, serif; font-weight: 600; font-size: 21px; color: #1C1713; margin-top: 3px; line-height: 1.25; }
.qc-total { font-weight: 700; font-size: 23px; color: #7C5E12; margin-top: 10px; }
.qc-rule { display: block; height: 1px; margin: 0 22px; background: linear-gradient(90deg, transparent, #C9A84C 20%, #C9A84C 80%, transparent); }
.qc-rows { padding: 16px 22px 22px; }
.qc-row { display: flex; justify-content: space-between; gap: 14px; font-size: 13px; color: #6B5E50; padding: 7px 0; border-bottom: 1px dashed #E8E0D0; }
.qc-note { padding: 0 24px 14px; text-align: center; font-size: 10px; font-style: italic; color: #A39884; line-height: 1.4; }

/* ── The catalogue page, as CatalogPrintPage draws it ──────────────────── */
.cp { background: #fff; padding: 16px; font-family: "Jost", var(--f-sans); color: #1a1000; }
.cp-head { text-align: center; margin-bottom: 16px; }
.cp-shop { font-size: 17px; font-weight: 800; color: #2a1a00; }
.cp-sub { font-size: 11px; color: #8a7050; margin-top: 2px; }
.cp-grid { display: grid; gap: 10px; }
.cp-row { display: flex; gap: 10px; }
.cp-cell, .cp-pad { flex: 1 1 0; min-width: 0; }
.cp-cell { border: 1px solid #e0d4b8; border-radius: 8px; overflow: hidden; }
.cp-cell img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
.cp-cap { padding: 7px 8px 9px; }
.cp-id { font-size: 8px; color: #9a8060; letter-spacing: .5px; margin-bottom: 3px; }
.cp-name { font-size: 10px; font-weight: 700; color: #1a1000; line-height: 1.35; margin-bottom: 4px; }
.cp-price { font-size: 12px; font-weight: 800; color: #a07820; }

/* ── Close ─────────────────────────────────────────────────────────────── */

.close-band { background: var(--velvet); color: var(--on-velvet); padding: clamp(70px, 11vh, 128px) 0; margin-top: clamp(40px, 7vh, 90px); }
.close-band .stage { position: relative; z-index: 2; }
.price-row { display: flex; flex-wrap: wrap; gap: clamp(24px, 5vw, 64px); margin-top: 38px; }
.price-cell .anno { display: block; margin-bottom: 9px; color: var(--on-velvet-sub); }
.price-cell .fig { font-size: clamp(1.8rem, 4vw, 2.8rem); color: var(--gold-light); }
.price-cell small { display: block; margin-top: 6px; font-size: 12.5px; color: var(--on-velvet-sub); }

/* ── Footer ────────────────────────────────────────────────────────────── */

.foot { background: var(--velvet); color: var(--on-velvet-sub); padding: 0 0 44px; font-size: 14px; }
.foot-in { max-width: var(--sheet); margin: 0 auto; padding: 0 var(--gutter); }
.foot-top { border-top: 1px solid var(--velvet-edge); padding-top: 44px; display: grid; gap: 34px; grid-template-columns: 1fr; }
@media (min-width: 768px) { .foot-top { grid-template-columns: 1.6fr 1fr 1fr; } }
.foot h4 { font-family: var(--f-mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--on-velvet); font-weight: 400; margin-bottom: 14px; }
.foot ul { list-style: none; display: grid; gap: 4px; }
.foot ul a { display: inline-flex; min-height: 44px; align-items: center; text-decoration: none; transition: color .2s; }
.foot ul a:hover { color: var(--on-velvet); }
.foot .wordmark { color: var(--on-velvet); }
.fine { border-top: 1px solid var(--velvet-edge); margin-top: 38px; padding-top: 22px; font-size: 12.5px; display: grid; gap: 7px; }
.fine a { text-decoration: none; }

/* ── Motion ────────────────────────────────────────────────────────────────
   Content is visible by default. `html.js` is set by an inline script in the
   head, so a blocked or failed script can never leave this page blank — the
   same failsafe the folio pages use. */
.html-js .rise { opacity: 0; transform: translate3d(0, 26px, 0); }
.rise { transition: opacity .9s var(--ease-out), transform .9s var(--ease-out); }
.rise.in { opacity: 1; transform: none; }
.rise.d1 { transition-delay: .09s } .rise.d2 { transition-delay: .18s }
.rise.d3 { transition-delay: .27s } .rise.d4 { transition-delay: .36s }

/* On a reduced-motion machine this page must still WORK, not go blank and
   static: the demonstrations are the content. So the entrances collapse to a
   short fade, the infinite loops stop, and every state change still happens.

   THE REVEAL RULE MUST BE RESTATED HERE, and leaving it out is what blanked the
   whole page on every reduced-motion machine. `.html-js .rise` and `.rise.in`
   carry the SAME specificity (two classes each), so between them source order
   decides — and this block sits after the reveal above. Re-hiding `.rise` here
   therefore beat `.rise.in`, and a page whose sections were all correctly marked
   revealed still painted nothing but the masthead and the footer, which carry no
   `.rise`. Reported from Edge on 2026-08-03; Chrome on the same desktop did not
   match reduced-motion, which is why it looked like a browser fault.
   `.html-js .rise.in` is deliberately one class heavier than anything that hides,
   so no future rule can win by being written later. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .html-js .rise { transform: none; }
  .html-js .rise.in { opacity: 1; transform: none; }
  .rise { transition: opacity .34s linear; }
  .tray::after { display: none; }
  .switch.live .live-dot { animation: none; }
  .piece-shot img { transition: none; }

  /* The films STAY. They are scroll-linked, not autonomous: nothing moves that
     the reader is not moving, which is the behaviour reduced-motion asks for
     rather than the behaviour it objects to — and they are the content, so
     replacing them with stills would empty the page for exactly the machines
     this workspace's own desktop happens to be one of. What does change is the
     rail: a shorter one means less of the page is spent pinned. */
  .html-js .film-rail { height: calc(100vh + 110vh); height: calc(100svh + 110vh); }
  .sheet-back, .sheet-panel { transition: none; }
}

/* The tray's own label. Two jobs: it names whose stock this is — which is the
   page's whole proof — and it gives the tray enough height to sit level with
   the thesis beside it instead of floating in the middle of an empty column. */
.tray-head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding-bottom: 14px; margin-bottom: 16px;
  border-bottom: 1px solid rgba(201,169,94,.22);
}

/* The quote act answers on paper, not on velvet — but a bare column of figures
   on the page ground read as the flattest passage on the page. It is the card
   she is about to be sent, so it is drawn as one. */
.quote-card {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: clamp(20px, 2.6vw, 30px);
  box-shadow: 0 1px 0 rgba(255,253,247,.6) inset, 0 18px 40px -26px rgba(60,38,12,.45);
}
.quote-card .readout { border-top: none; padding-top: 8px; margin-top: 14px; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE INNER PAGES — /inside-the-app/, /pricing/, /contact/, /terms/,
   /refunds/, /privacy/

   These were the bahi-khata folio: a cream sheet on a darker desk, a red
   margin rule down the left, Cormorant Garamond, atelier.css. That stylesheet
   is gone and every page now loads THIS one, so the site is a single surface
   rather than a front door in one world and six rooms in another.

   What carries over from the front page, unchanged and deliberately:
     · the cream counter paper with its grain, and the fixed masthead over it
     · Fraunces for every heading and every rupee figure, DM Mono for the
       annotation, Inter Tight for reading
     · the velvet, which is what a section used to do with `.band-ink` — but
       drawn as a TRAY, since that is the front page's one structural object
       and a full-bleed ink slab would be a second, competing one.

   The folio's own furniture is kept where it earns its place: the ledger
   entry with its amount column, the ruled register, the tick list, the clause
   index. Those are how a jeweller's paper actually reads, and they are the
   reason these pages are not a SaaS feature grid. The red margin rule, the
   panel sheet and its desk are what have gone — on this ground they were a
   second world.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Three tokens the folio pages need that the front page never did.
     --f-serif is an ALIAS, not a second face: the replicas in
     /inside-the-app/ ask for it by name, and on this site the serif IS the
     display face. */
  --f-serif:   var(--f-display);
  --gold-pale: #FCF4DA;
  --header:    #EAE0CB;   /* the app's own header band, used by the replicas */
  --cash-rule: #9AAE7D;
}

/* The masthead is FIXED here as it is on the front page, and the front page
   pays for it inside .hero's own padding. An inner page has no hero, so the
   body carries it — without this the first annotation sits under the bar. */
body.page main { padding-top: 68px; }

/* ── The sheet, and the folio it is ruled into ─────────────────────────── */

/* Was the panel-coloured, shadowed ledger leaf lying on a desk. The desk went
   with atelier.css, so this is now nothing but the flow — kept as a hook
   rather than stripped out of six files' markup. */
.sheet { position: relative; }

/* One folio = one measure of the page, matching .stage exactly, so a section
   on /pricing/ lines up with a section on the front page. */
.folio {
  max-width: var(--sheet);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.band { border-top: 1px solid var(--rule-faint); }
.band:first-of-type { border-top: 0; }

.band-pad    { padding-block: clamp(48px, 7vw, 92px); }
.band-pad-lg { padding-block: clamp(60px, 9vw, 124px); }
.band-pad-sm { padding-block: clamp(34px, 4.6vw, 62px); }

/* The passage that has to stop the scroll — the prices, the ways to reach a
   person. Velvet, and drawn as the front page's tray rather than as a slab of
   ink bleeding to both edges: the tray is this product's object, and a page
   that is mostly reading should carry exactly one of them. */
.band-ink {
  position: relative;
  color: var(--on-velvet);
  border-top: 0;
  /* A tray is an object lying ON the counter, so it is inset from the page's
     edges rather than running to them: the section keeps the folio's measure
     but spends the gutter as its own margin, and carries the tray's padding
     inside. Without the width calc it painted flush to a phone's screen edges
     and the rounded corners had nothing to sit against. */
  width: calc(100% - 2 * var(--gutter));
  margin-block: clamp(14px, 2vw, 26px);
  margin-inline: auto;
  padding-inline: clamp(22px, 3.4vw, 46px);
  border-radius: 6px;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(255,236,196,.11), transparent 62%),
    linear-gradient(178deg, var(--velvet-lift), var(--velvet) 62%);
  border: 1px solid var(--velvet-edge);
  box-shadow:
    0 1px 0 rgba(255,236,196,.10) inset,
    0 30px 70px -34px rgba(60,38,12,.55);
}
/* The velvet's nap, exactly as the tray carries it. */
.band-ink::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  border-radius: inherit;
  background-image:
    repeating-linear-gradient(97deg, rgba(255,255,255,.016) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(7deg,  rgba(0,0,0,.05) 0 1px, transparent 1px 4px);
  opacity: .8;
}
.band-ink > * { position: relative; z-index: 1; }
.band-ink h1, .band-ink h2, .band-ink h3 { color: var(--on-velvet); }
.band-ink h1 em, .band-ink h2 em, .band-ink h3 em { color: var(--gold-light); }
.band-ink .anno { color: var(--on-velvet-sub); }
.band-ink .lede, .band-ink .prose, .band-ink p { color: var(--on-velvet-sub); }
.band-ink .prose strong, .band-ink strong { color: var(--on-velvet); }
.band-ink .prose a, .band-ink .doc a, .band-ink a.prose { color: var(--gold-light); }
.band-ink .hair, .band-ink hr { border-color: var(--velvet-edge); }
.band-ink .fig { color: var(--gold-light); }

/* ── Type ──────────────────────────────────────────────────────────────── */

/* Sized off .display's own clamps, so a page heading and a front-page act
   heading are one voice at one size. */
h1, h2, h3 {
  font-family: var(--f-display);
  font-optical-sizing: auto;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -.018em;
  color: var(--ink-deep);
  text-wrap: balance;
}
h1 { font-size: clamp(2.5rem, 4.6vw, 4.05rem); }
h2 { font-size: clamp(2.1rem, 3.9vw, 3.4rem); }
/* A section that supports rather than claims — the register of everything
   else, the questions column. Same face, one step down. */
h2.h2-quiet { font-size: clamp(1.55rem, 2.7vw, 2.3rem); }
h3 { font-size: clamp(1.2rem, 1.7vw, 1.5rem); font-weight: 600; letter-spacing: -.012em; line-height: 1.2; }
h1 em, h2 em, h3 em { font-style: italic; color: var(--gold-text); }

.prose { max-width: 68ch; color: var(--ink-sub); line-height: 1.65; }
.prose + .prose { margin-top: .9em; }
.prose strong { color: var(--ink-deep); font-weight: 600; }
.prose a { color: var(--gold-text); text-underline-offset: 3px; }

.label {
  font-family: var(--f-mono); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--gold-text);
}

.hair { border: 0; border-top: 1px solid var(--rule); }

.stack  { display: flex; flex-direction: column; }
.gap-sm { gap: 10px; } .gap-md { gap: 18px; } .gap-lg { gap: 30px; }
.mt-sm  { margin-top: 14px; } .mt-md { margin-top: 26px; } .mt-lg { margin-top: 44px; }

.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* The folio pages' second button. It is the front page's ghost button under
   another name — kept as an alias so six files' markup did not have to be
   re-typed to say the same thing. */
.btn-ink { background: transparent; color: var(--ink-deep); border-color: var(--rule-strong); }
.band-ink .btn-ink { color: var(--on-velvet); border-color: var(--velvet-edge); }
@media (hover: hover) and (pointer: fine) {
  .btn-ink:hover { background: rgba(42,33,26,.05); border-color: var(--ink-faint); }
  .band-ink .btn-ink:hover { background: rgba(240,231,214,.07); }
}
.btn-sm { min-height: 42px; padding: 11px 18px; font-size: 12px; }

.split.narrow-first { grid-template-columns: 1fr; }
@media (min-width: 768px) { .split.narrow-first { grid-template-columns: .82fr 1.18fr; } }

/* ── The ledger entry — the folio's structural unit ─────────────────────
   Annotation in the margin · the entry itself · the amount column. This is
   the piece of the old folio that does the most work: it is what makes a
   price list and a set of steps read as postings rather than as cards. */

.entries { border-top: 1px solid var(--rule); }
.entry {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "a" "b" "m";
  gap: 6px clamp(20px, 3vw, 44px);
  padding-block: clamp(26px, 3.4vw, 42px);
  border-bottom: 1px solid var(--rule-faint);
}
.entry:last-child { border-bottom: 0; }
.entry-anno { grid-area: a; }
.entry-body { grid-area: b; }
.entry-amt  { grid-area: m; }
.entry-body h3 { margin-bottom: .45rem; }
.entry-body .prose { max-width: 56ch; }

/* Below 768px the amount column does not exist — the entry stacks a/b/m — so
   a 2.5rem serif numeral landing after the paragraph would read as a mis-set
   heading rather than as a posted amount. On a phone it is a caption. */
.entry-amt { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.entry-amt .fig { font-size: 1.4rem; color: var(--ink-deep); }
.entry-amt .unit {
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-sub);
}
@media (min-width: 768px) {
  .entry { grid-template-columns: 8.5rem minmax(0, 1fr) minmax(0, 15rem); grid-template-areas: "a b m"; align-items: start; }
  .entry-anno { padding-top: .5rem; }
  .entry-amt { display: block; text-align: right; padding-top: .2rem; }
  .entry-amt .fig { font-size: clamp(1.9rem, 2.6vw, 2.5rem); display: block; }
  .entry-amt .unit { display: block; margin-top: 5px; }
  /* An entry with nothing to post drops the column rather than holding 15rem
     of empty ledger open beside itself. */
  .entry-plain { grid-template-columns: 8.5rem minmax(0, 1fr); grid-template-areas: "a b"; }
}
/* Stated after the velvet block and not left to it: these carry identical
   specificity to `.band-ink .fig`, so the later rule wins outright. Without
   them the amount column on a velvet folio is painted ink on ink. */
.band-ink .entry-amt .fig  { color: var(--gold-light); }
.band-ink .entry-amt .unit { color: var(--on-velvet-sub); }
.band-ink .entries, .band-ink .entry { border-color: var(--velvet-edge); }

/* ── A ruled register of plain facts ───────────────────────────────────── */

.reg { border-top: 1px solid var(--rule-faint); }
/* One column on a phone. With `1fr auto` a long label wrapped to two lines
   while the value stayed baseline-aligned to the first, leaving an orphan
   word under a value that had already moved on. */
.reg li {
  list-style: none;
  display: grid; grid-template-columns: 1fr; gap: 2px;
  padding: 12px 0; border-bottom: 1px solid var(--rule-faint);
}
@media (min-width: 768px) {
  .reg li { grid-template-columns: 1fr auto; gap: 8px 20px; align-items: baseline; }
}
.reg li > span:first-child { color: var(--ink-sub); }
.reg li > .fig, .reg li > strong { color: var(--ink-deep); font-weight: 600; white-space: nowrap; }
.band-ink .reg, .band-ink .reg li { border-color: var(--velvet-edge); }
.band-ink .reg li > span:first-child { color: var(--on-velvet-sub); }
.band-ink .reg li > strong { color: var(--on-velvet); }

/* ── A tick list, in the world's grammar — a drawn mark, not a glyph ───── */

.ticks { list-style: none; display: grid; gap: 11px; }
.ticks li { display: grid; grid-template-columns: 15px 1fr; gap: 12px; align-items: start; color: var(--ink-sub); }
/* Gold leaf is 2.09:1 on cream — under the 3:1 floor for a mark that carries
   meaning. The deep gold is its readable counterpart; on velvet the leaf is
   8.10:1 and is the right one there. */
.ticks svg { margin-top: .42em; color: var(--gold-text); flex: none; }
.band-ink .ticks li { color: var(--on-velvet-sub); }
.band-ink .ticks svg { color: var(--gold-light); }

.callout {
  border: 1px solid var(--gold);
  background: var(--gold-pale);
  border-radius: 6px;
  padding: clamp(16px, 2.4vw, 26px);
  margin-top: 26px;
}
.callout p { color: var(--ink); }

/* ── Read-mode pages: the policies ─────────────────────────────────────── */

/* 62ch lands around 78 real characters on Inter Tight — the comfortable band.
   A clause is read once, carefully, and never scanned. */
.doc { max-width: 62ch; }
.doc h2 { font-size: clamp(1.45rem, 2.3vw, 1.95rem); margin-top: clamp(34px, 4vw, 52px); margin-bottom: .6rem; }
.doc h2:first-of-type { margin-top: 0; }
.doc h3 { font-size: clamp(1.08rem, 1.5vw, 1.25rem); margin-top: 26px; margin-bottom: .4rem; }
.doc p, .doc ul, .doc ol { color: var(--ink-sub); line-height: 1.65; }
.doc p + p, .doc p + ul, .doc ul + p, .doc p + ol, .doc ol + p { margin-top: .85em; }
.doc ul, .doc ol { padding-left: 1.15em; }
.doc li { margin-top: .38em; }
.doc li::marker { color: var(--gold-text); }
.doc strong { color: var(--ink-deep); font-weight: 600; }
.doc a { color: var(--gold-text); text-underline-offset: 3px; }
/* The masthead is fixed, so a clause jumped to from the index would otherwise
   land underneath it. */
.doc h2[id], .doc h3[id] { scroll-margin-top: 88px; }

/* The index of clauses — the ledger's own contents page. Every clause is
   already numbered, so this costs nothing and makes a long document
   navigable. */
.toc { margin-top: 26px; max-width: 62ch; }
.toc-hd {
  font-family: var(--f-mono); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-sub); margin-bottom: 10px;
}
.toc ol { list-style: none; padding: 0; display: grid; gap: 0; border-top: 1px solid var(--rule-faint); }
@media (min-width: 768px) { .toc ol { grid-template-columns: 1fr 1fr; column-gap: clamp(20px, 3vw, 44px); } }
.toc li { border-bottom: 1px solid var(--rule-faint); margin: 0; }
.toc a {
  display: flex; align-items: baseline; gap: 10px;
  min-height: 44px; padding: 6px 0;
  color: var(--ink-sub); text-decoration: none; font-size: 14px;
}
.toc a:hover { color: var(--ink-deep); }
.toc a .n { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .1em; color: var(--gold-text); flex: none; min-width: 1.6em; }

/* ── The screen replicas on /inside-the-app/ ───────────────────────────
   Not screenshots: the app rebuilt from the same tokens, so it cannot look
   like a different product. Everything here is SCOPED UNDER .device, because
   `.piece` and `.strip` are also the front page's own classes and mean
   something else there — a piece lying on velvet, and its material bar. */

.device {
  width: 100%; max-width: 330px;
  background: var(--velvet);
  border-radius: 30px;
  padding: 10px;
  border: 1px solid var(--velvet-edge);
  box-shadow: 0 2px 2px rgba(60,45,25,.2), 0 30px 60px -24px rgba(52,38,18,.6);
}
.device-in {
  background: var(--paper);
  border-radius: 21px;
  overflow: hidden;
  display: flex; flex-direction: column;
  /* The last row's strip otherwise sits hard against the rounded bottom edge
     and reads as cut off. */
  padding-bottom: 6px;
}
.scr-bar { background: var(--header); border-bottom: 1px solid var(--rule); padding: 10px 12px; display: flex; align-items: baseline; gap: 8px; }
.scr-bar .shop { font-family: var(--f-display); font-size: 15px; font-weight: 600; color: var(--ink-deep); }
.scr-bar .live {
  margin-left: auto; font-family: var(--f-mono); font-size: 8.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--cash-text);
  display: inline-flex; align-items: center; gap: 5px;
}
.scr-bar .live .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--cash-rule); }

.rate-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--rule); }
.rate-cell { background: var(--panel); padding: 9px 10px; }
.rate-cell .k { font-family: var(--f-mono); font-size: 8.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--gold-text); }
.rate-cell .v {
  font-family: var(--f-display); font-weight: 600; font-size: 17px; color: var(--ink-deep);
  font-variant-numeric: lining-nums tabular-nums; margin-top: 3px;
}

.device .piece { padding: 11px 12px; border-bottom: 1px solid var(--rule-faint); }
.device .piece:last-child { border-bottom: 0; }
.piece-hd { display: flex; align-items: baseline; gap: 8px; }
.piece-hd .nm { font-family: var(--f-display); font-size: 15.5px; font-weight: 600; color: var(--ink-deep); line-height: 1.2; }
.piece-hd .tg { font-family: var(--f-mono); font-size: 8.5px; letter-spacing: .1em; color: var(--ink-sub); }
.piece-hd .pr {
  margin-left: auto; font-family: var(--f-display); font-weight: 600; font-size: 17px;
  color: var(--ink-deep); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap;
}
/* The five material tints run as low as 1.00:1 against each other, so with no
   separator the whole strip paints as one beige rule and the pattern says
   nothing. The boundaries are hairlines and the bar is tall enough to read. */
.device .strip {
  display: flex; gap: 1px; margin-top: 8px; height: 11px;
  border: 0; border-radius: 2px; overflow: hidden;
  background: var(--rule-strong); box-shadow: 0 0 0 1px var(--rule-strong);
}
.device .strip i + i { border-left: 0; }
.piece-ft { margin-top: 7px; display: flex; gap: 10px; font-size: 10px; line-height: 1.4; color: var(--ink-sub); }

/* The value that recomputes when the rate ticks. */
.tick { transition: color .5s var(--ease-out); }
.tick.up { color: var(--gold-text); }

@media print {
  body { background: #fff; }
  .masthead, .device { display: none; }
  body.page main { padding-top: 0; }
}
