/* ==========================================================================
   Ranbix — dev site
   Palette sampled from the brand mark: red #FB2C23, green #00913A / #197909
   Light editorial body, dark hero and feature bands. Single committed look —
   no light/dark toggle.
   ========================================================================== */

:root{
  /* brand */
  --red:#E01E14;
  --red-hi:#FB2C23;
  --red-soft:#FEF1F0;
  --green:#00913A;
  --green-deep:#197909;
  --green-soft:#EAF7EF;

  /* neutrals */
  --ink:#0D1822;
  --ink-2:#2A3B4A;
  --muted:#61748A;
  --line:#E3E9EF;
  --canvas:#FFFFFF;
  --soft:#F5F8FB;

  /* dark band */
  --deep:#0A141D;
  --deep-2:#101F2B;
  --deep-line:rgba(255,255,255,.10);
  --deep-ink:#EAF1F7;
  --deep-mute:#93A9BC;

  --r:14px;
  --r-lg:22px;
  --r-xl:30px;
  --wrap:1200px;

  --sh-1:0 1px 2px rgba(13,24,34,.05), 0 10px 28px rgba(13,24,34,.06);
  --sh-2:0 30px 70px rgba(13,24,34,.16);

  /* Nunito carries the headings and anything else set heavy; Montserrat carries
     running text. Montserrat is the wider of the two, so measures below are set in
     ch and were re-checked after the swap rather than left at their Manrope values. */
  --display:'Nunito',system-ui,-apple-system,'Segoe UI',sans-serif;
  --sans:'Montserrat',system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  --ease:cubic-bezier(.22,.61,.36,1);
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;scroll-padding-top:88px}

body{
  margin:0;
  font-family:var(--sans);
  font-size:16.5px;
  line-height:1.65;
  color:var(--ink-2);
  background:var(--canvas);
  -webkit-font-smoothing:antialiased;
}

img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
p{margin:0}
h1,h2,h3,h4{margin:0;font-family:var(--display);color:var(--ink);line-height:1.12;letter-spacing:-.024em;font-weight:800}
h1{font-size:clamp(2.5rem,5.6vw,4.35rem)}
h2{font-size:clamp(1.85rem,3.5vw,2.85rem)}
h3{font-size:clamp(1.08rem,1.5vw,1.28rem);letter-spacing:-.016em}
h4{font-size:.78rem;letter-spacing:.14em;text-transform:uppercase}

code{font-family:var(--mono);font-size:.86em;background:var(--soft);
  border:1px solid var(--line);border-radius:6px;padding:.12em .42em}

/* padding-inline, not the padding shorthand: several blocks are `class="wrap x"`
   and set their own vertical padding — .foot__in and .foot__base among them. The
   shorthand here reset that to 0, which on a phone dropped the footer's columns
   flush against the copyright bar. */
.wrap{width:100%;max-width:var(--wrap);margin:0 auto;padding-inline:26px}
.wrap--narrow{max-width:860px}

.skip{
  position:absolute;left:-9999px;top:0;z-index:200;
  background:var(--red);color:#fff;padding:12px 20px;border-radius:0 0 10px 0;font-weight:700;
}
.skip:focus{left:0}

:focus-visible{outline:3px solid var(--red-hi);outline-offset:3px;border-radius:6px}

/* ---------------------------------------------------------------- atoms -- */
.eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-size:0.75rem;font-weight:800;letter-spacing:.17em;text-transform:uppercase;
  color:var(--red);background:var(--red-soft);
  padding:7px 14px;border-radius:999px;margin-bottom:20px;
}
.eyebrow--dark{color:#FFB3AE;background:rgba(251,44,35,.14);border:1px solid rgba(251,44,35,.24)}
/* Green rather than red for the clinic band — KLINIK is the sibling product, and the
   colour is what separates it from the pharmacy's own sections at a glance. */
.eyebrow--alt{color:var(--green-deep);background:var(--green-soft)}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:13px 24px;border-radius:999px;
  font-family:var(--display);font-weight:800;font-size:.93rem;letter-spacing:-.005em;
  border:2px solid transparent;cursor:pointer;white-space:nowrap;
  transition:transform .2s var(--ease),box-shadow .2s var(--ease),
             background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease);
}
.btn--lg{padding:16px 30px;font-size:1rem}
/* No coloured glow at rest. A 26px red blur under a red pill reads as a smudge on
   the white nav rather than a lift — so the glow is hover feedback now, and the
   resting state is a clean edge. */
.btn--solid{background:var(--red);color:#fff;box-shadow:0 1px 2px rgba(13,24,34,.10)}
.btn--solid:hover{background:var(--red-hi);transform:translateY(-2px);box-shadow:0 10px 24px rgba(224,30,20,.30)}
/* var(--line) is a hairline meant for dividers; on a button it left the outline
   barely visible next to the solid red beside it. */
.btn--ghost{color:var(--ink);border-color:#D5DFE8;background:#fff}
.btn--ghost:hover{border-color:var(--ink);transform:translateY(-2px)}
.btn--line{color:var(--deep-ink);border-color:rgba(255,255,255,.28)}
.btn--line:hover{border-color:#fff;background:rgba(255,255,255,.08);transform:translateY(-2px)}

/* The sprite is a definitions carrier, never painted itself. Collapsed rather than
   display:none — a few engines have historically dropped <use> references into a
   display:none subtree, and zero-size overflow:hidden has no such edge case. */
.sprite{position:absolute;width:0;height:0;overflow:hidden}
.btn__ico{width:16px;height:16px;flex:0 0 auto;fill:currentColor}

/* The mark carries WhatsApp's own green rather than inheriting the label's ink.
   At 16px a monochrome dark version reads as an anonymous speech bubble; the green
   is what makes it identifiable at a glance, and it is the one spot of colour that
   tells the two nav buttons apart at speed. */
.btn--wa .btn__ico{fill:#25D366}
.btn--wa:hover{border-color:var(--green);color:var(--green-deep)}
/* That hover ink is chosen for the white nav. On a dark band it is near-black text on
   near-black — so the WhatsApp button there keeps the light label and only the border
   picks up the green. */
.sec--dark .btn--wa:hover,.cta .btn--wa:hover{color:#fff}

.grad{
  background:linear-gradient(96deg,var(--red-hi) 0%,#FF7A4D 46%,var(--green) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}

/* screenshot frame */
.frame{
  border-radius:var(--r-lg);overflow:hidden;background:#0F1D28;
  border:1px solid rgba(255,255,255,.12);box-shadow:var(--sh-2);
}
.frame__bar{
  display:flex;align-items:center;gap:7px;
  padding:11px 16px;background:#162734;border-bottom:1px solid rgba(255,255,255,.08);
}
.frame__bar i{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.2)}
.frame__bar i:first-child{background:#FF5F57}
.frame__bar i:nth-child(2){background:#FEBC2E}
.frame__bar i:nth-child(3){background:#28C840}
.frame__bar span{
  margin-left:10px;font-family:var(--mono);font-size:.72rem;color:var(--deep-mute);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.frame img{width:100%;height:auto;display:block}

/* ------------------------------------------------------------------ nav -- */
.nav{
  position:sticky;top:0;z-index:100;
  /* Sits over both light and dark bands — keep it opaque enough that the dark
     sections behind it don't muddy the white to grey. */
  background:rgba(255,255,255,.94);backdrop-filter:saturate(180%) blur(16px);
  -webkit-backdrop-filter:saturate(180%) blur(16px);
  border-bottom:1px solid transparent;transition:border-color .25s,box-shadow .25s;
}
.nav.is-stuck{border-bottom-color:var(--line);box-shadow:0 6px 24px rgba(13,24,34,.06)}
.nav__in{display:flex;align-items:center;gap:26px;height:76px}

/* The lockup's capsules sit above and below the wordmark, so a good deal of its
   height is artwork rather than text — it needs more room than a plain wordmark to
   stay legible, and 40px is about the floor before "PHARMA SOFT" breaks up. */
.brand img{height:50px;width:auto}

/* align-items:center so the Products button sits on the same baseline as the
   plain links, which are inline text and it is not. */
.nav__links{display:flex;align-items:center;gap:26px;margin-left:auto}

/* The shared .btn padding plus the body's 1.65 line-height made these 55px tall in
   a 76px bar — only 10px of air above and below. Tighter here only; the hero and
   CTA buttons want the larger hit area. */
.nav__cta{display:flex;gap:10px}
.nav__cta .btn{padding:12px 20px;font-size:.9rem;line-height:1.2}

.burger{
  display:none;width:44px;height:44px;border:1px solid var(--line);border-radius:12px;
  background:#fff;cursor:pointer;padding:0;
  /* An explicit gap rather than margins on the bars: it makes the distance between
     them a number this file states, so the close-state translate below can match it
     exactly. Left to grid auto-distribution the bars sat 14px apart while the
     translate moved them 6px, and the X never closed — it read as a chevron. */
  justify-items:center;align-content:center;gap:5px;
}
.burger span{display:block;width:19px;height:2px;background:var(--ink);margin:0;
  border-radius:2px;transition:transform .25s var(--ease),opacity .2s}
/* 7px = the 5px gap + the 2px bar. Keep in step with the gap above. */
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

.drawer{
  display:none;flex-direction:column;gap:2px;padding:12px 26px 26px;
  background:#fff;border-top:1px solid var(--line);
}
.drawer a{padding:14px 2px;font-weight:700;color:var(--ink);border-bottom:1px solid var(--line)}
.drawer__wa{display:flex;align-items:center;gap:10px;color:var(--green-deep)}
.drawer__cta{margin-top:18px;border-bottom:0;justify-content:center;color:#fff}

/* ----------------------------------------------------------------- hero -- */
/* Split down the middle: copy on the dark left, a staged device scene bleeding off
   the right edge. The stage carries no words that matter, so on a narrow screen it
   drops below the copy rather than fighting it for room. */
.hero{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.06fr);align-items:center;
  color:var(--deep-ink);overflow:hidden;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150' viewBox='0 0 150 150'%3E%3Cg fill='none' stroke='%23ffffff' stroke-opacity='.055' stroke-width='1.6'%3E%3Crect x='18' y='24' width='44' height='17' rx='8.5' transform='rotate(-24 40 32)'/%3E%3Cpath d='M40 24v17' transform='rotate(-24 40 32)'/%3E%3Crect x='92' y='96' width='40' height='16' rx='8' transform='rotate(16 112 104)'/%3E%3Cpath d='M112 96v16' transform='rotate(16 112 104)'/%3E%3Cpath d='M104 26h13M110.5 19.5v13'/%3E%3Cpath d='M30 108h11M35.5 102.5v11'/%3E%3C/g%3E%3C/svg%3E") repeat,
    radial-gradient(900px 620px at 10% 6%, rgba(251,44,35,.20), transparent 62%),
    linear-gradient(180deg,var(--deep) 0%,var(--deep-2) 100%);
  background-size:150px 150px, auto, auto;
}

.hero__copy{
  display:flex;align-items:center;position:relative;z-index:1;
  /* Left padding tracks the page gutter, so the hero copy starts on exactly the
     same line as every .wrap section below it even though the hero is full-bleed. */
  /* Tighter than it looks like it should be. The stage stretches to match this
     column, and the scene is 4:3 — every extra pixel of padding here makes the
     stage taller, which makes cover() throw away more of the image's width. */
  padding:clamp(40px,4.4vw,64px) clamp(26px,4vw,56px) clamp(40px,4.4vw,64px)
          max(26px, calc((100vw - var(--wrap)) / 2));
}
/* The copy stays aligned to the page's grid even though the section is full-bleed. */
.hero__copyin{width:100%;max-width:calc(var(--wrap) / 2 - 26px)}
.hero h1{color:#fff;margin-bottom:20px}
.lede{font-size:clamp(1.03rem,1.35vw,1.2rem);color:var(--deep-mute);max-width:52ch}
.hero__actions{display:flex;flex-wrap:wrap;gap:14px;margin:28px 0 26px}
.hero__ticks{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.hero__ticks li{position:relative;padding-left:30px;font-size:.93rem;color:var(--deep-mute)}
.hero__ticks li::before{
  content:"";position:absolute;left:0;top:.52em;width:16px;height:16px;border-radius:50%;
  background:rgba(0,145,58,.2);box-shadow:inset 0 0 0 1.5px rgba(0,197,80,.55);
}
.hero__ticks li::after{
  content:"";position:absolute;left:5.4px;top:.78em;width:4.5px;height:8px;
  border:solid #4FD989;border-width:0 2px 2px 0;transform:rotate(42deg);
}

/* --- the stage --- */
/* The scene keeps its own 4:3 and is never cropped. Stretching it to match the
   copy column meant cover() threw away a quarter of the image width — and what it
   threw away was the right-hand edge of the tablet. It sits centred on the dark
   instead, bleeding off the right edge, rounded on the side that stays on-screen. */
.hero__stage{position:relative;display:flex;align-items:center;padding:clamp(20px,3vw,40px) 0}
.hero__scene{
  width:100%;height:auto;display:block;
  border-radius:20px 0 0 20px;
  box-shadow:0 34px 70px rgba(0,0,0,.42), 0 4px 14px rgba(0,0,0,.28);
}
/* A soft shadow pooling under the devices, so they sit on the wood rather than
   being pasted onto it. */




@media (max-width:980px){
  .hero{grid-template-columns:1fr}
  .hero__copy{padding:clamp(48px,8vw,80px) 26px 40px}
  .hero__copyin{max-width:none;margin:0}
  .hero__stage{min-height:340px}
      }
@media (max-width:560px){
  .hero__stage{min-height:250px}
  }




/* ---------------------------------------------------------------- proof -- */
/* No .wrap on this one. The band is the full width of the window on purpose — a
   marquee that stops at a 1200px measure reads as a broken row, not a running one. */
.proof{background:var(--deep-2);border-block:1px solid var(--deep-line);padding:0}

.ticker{display:flex;overflow:hidden;position:relative}
/* The edges fade into the band instead of cutting a sentence off mid-letter.
   mask rather than a pair of gradient overlays: one property, and it keeps working
   whatever sits behind the band. */
.ticker{
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.ticker__track{
  display:flex;align-items:center;flex:none;min-width:100%;
  list-style:none;margin:0;padding:0;
  animation:tick 46s linear infinite;
}
.ticker:hover .ticker__track{animation-play-state:paused}
.ticker__track li{
  padding:22px 0;white-space:nowrap;
  font-family:var(--display);font-weight:700;font-size:1.02rem;color:var(--deep-ink);
}
/* The separator is a pseudo-element on the item, not a character in the markup —
   the text stays clean for a screen reader and for anyone copying a line out. */
.ticker__track li::after{
  content:"";display:inline-block;vertical-align:middle;
  width:6px;height:6px;margin:0 30px;border-radius:50%;
  background:var(--red-hi);opacity:.9;
}
@keyframes tick{ to{ transform:translateX(-100%) } }

/* -------------------------------------------------------------- section -- */
.sec{padding:clamp(72px,9vw,120px) 0}
.sec--soft{background:var(--soft);border-block:1px solid var(--line)}
.sec--dark{background:var(--deep);color:var(--deep-mute)}
.sec--dark h2,.sec--dark h3{color:#fff}

/* Centred: the measure was already capped at 760px, so the block was a narrow
   column pinned to the left of a 1200px wrap. margin-inline:auto centres the box
   and text-align centres what is in it — including the eyebrow, which is an
   inline-block pill and follows the text alignment of its parent. */
.sechead{max-width:760px;margin-inline:auto;text-align:center;margin-bottom:clamp(40px,5vw,60px)}
.sechead__sub{margin-top:20px;font-size:1.04rem;color:var(--muted)}
.sechead--dark .sechead__sub{color:var(--deep-mute)}

.grid{display:grid;gap:18px}

/* -------------------------------------------------------- prescription -- */
/* Printed letterhead, handwritten body — which is what a real script is. Everything
   the pharmacy printed is in the site's own faces; everything a person would have
   written is in Kalam, in blue-black ink. That single split is most of the realism. */
:root{ --ink-pen:#1E3566; }

.rxpad{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(20px,3vw,34px);align-items:start;
}

.ink{
  font-family:'Kalam','Segoe Script','Bradley Hand',cursive;
  color:var(--ink-pen);font-weight:400;
}

/* Two loose sheets behind each script, at their own angles. A box-shadow can fake
   a pad's edge but not a bunch of paper — these are real boxes, so the corners show
   past the top sheet the way a pile actually does. */
.rxsheet{position:relative;isolation:isolate}
.rxsheet:first-child{transform:rotate(-.5deg)}
.rxsheet:last-child{transform:rotate(.4deg)}
.rxsheet::before,.rxsheet::after{
  content:"";position:absolute;inset:0;z-index:-1;
  background:#FAF6EE;border:1px solid #E6E1D4;border-radius:3px;
  box-shadow:0 10px 22px rgba(13,24,34,.10);
}
.rxsheet::before{transform:rotate(-2.2deg) translate(-7px,5px)}
.rxsheet::after{transform:rotate(1.7deg) translate(6px,8px)}

.rx{
  position:relative;z-index:1;background:#FDFBF6;
  border:1px solid #E4DFD3;border-radius:3px;
  padding:20px clamp(16px,2vw,24px) 16px;
  box-shadow:0 1px 0 #F6F3EB, 0 2px 0 #F0ECE2, 0 22px 44px rgba(13,24,34,.16);
}
/* A faint warm cast down one edge, the way paper catches light. */
.rx::after{
  content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:linear-gradient(105deg, rgba(190,175,140,.10), transparent 26%, transparent 82%, rgba(190,175,140,.09));
}
.rx__perf{
  position:absolute;top:6px;left:12px;right:12px;height:5px;
  background:radial-gradient(circle,#D6D0C0 46%,transparent 48%) repeat-x;
  background-size:9px 5px;opacity:.9;
}

.rx__head{display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:center;
  padding-bottom:8px;border-bottom:2px solid var(--red)}
.rx__caduceus{color:var(--red)}
.rx__caduceus svg{fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;display:block}
.rx__brand b{display:block;font-size:.86rem;font-weight:800;letter-spacing:.03em;color:var(--ink);line-height:1.2}
.rx__brand>span{font-size:.64rem;color:var(--muted)}
.rx__reg{display:grid;text-align:right;font-family:var(--mono);font-size:.55rem;
  letter-spacing:.07em;text-transform:uppercase;color:#8C8574;line-height:1.8}

/* Fields you would write into. The label is printed; what fills it is not. */
.rx__patient{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 13px;padding:7px 0 4px}
.rx__f{display:inline-flex;align-items:baseline;gap:6px;flex:1 1 auto}
.rx__f--sm{flex:0 0 auto}.rx__f--xs{flex:0 0 auto}
.rx__f i,.rx__dx i,.rx__advice i{
  font-style:normal;font-family:var(--mono);font-size:.58rem;letter-spacing:.1em;
  text-transform:uppercase;color:#8C8574;
}
.rx__f u,.rx__dx u,.rx__advice u{
  text-decoration:none;border-bottom:1px solid #D3CCBA;flex:1 1 auto;min-width:44px;
  font-size:.92rem;line-height:1.2;padding:0 3px 1px;
}
.rx__f--xs u{min-width:30px}
.rx__dx{display:flex;align-items:baseline;gap:6px;padding-bottom:7px;border-bottom:1px solid #E4E0D4}

.rx__mark{font-family:var(--display);font-size:2rem;font-weight:800;color:var(--red);line-height:1;margin:7px 0 -2px}

.rx__list{list-style:none;margin:0;padding:0}
/* Ruled by borders, never a background gradient — a gradient must be told the row
   height and slips the moment a note wraps. */
.rx__item{
  display:grid;grid-template-columns:20px 18px minmax(0,1fr);gap:1px 7px;
  padding:7px 0 8px;border-bottom:1px solid #E9EEF4;
}
.rx__item:last-child{border-bottom:0}
.rx__no{font-family:'Kalam',cursive;font-size:.88rem;color:var(--ink-pen);opacity:.75;padding-top:1px}
.rx__ico{color:var(--red);align-self:start;padding-top:4px}
.rx__ico svg{fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;display:block}
.rx--shelf  .rx__ico{color:var(--green)}
.rx--office .rx__ico{color:var(--ink-2)}

/* The drug is written. The pharmacy's own note under it is printed. */
.rx__drug{
  grid-column:3;font-family:'Kalam',cursive;font-weight:700;
  font-size:1.04rem;line-height:1.18;color:var(--ink-pen);
}
.rx__dose{
  grid-column:3;font-family:'Kalam',cursive;font-size:.88rem;
  color:var(--ink-pen);opacity:.8;margin-top:0;
}
.rx__note{grid-column:3;font-size:.72rem;color:var(--muted);line-height:1.4;margin-top:2px}

.rx__foot{position:relative;display:grid;gap:8px;margin-top:10px;padding-top:9px;
  border-top:1px dashed #DCD7C8}
.rx__advice{display:flex;align-items:baseline;gap:6px}
.rx__signblock{display:grid;justify-items:end;gap:1px;justify-self:end}
.rx__sign{font-size:1.28rem;font-weight:700;transform:rotate(-6deg);line-height:1.05;padding-right:10px}
.rx__signrule{display:block;width:112px;border-bottom:1px solid #B7B0A0}
.rx__signlbl{font-family:var(--mono);font-size:.52rem;letter-spacing:.1em;text-transform:uppercase;color:#8C8574}

/* The rubber stamp every Indian script carries, sitting slightly askew and
   half-absorbed into the paper. */
.rx__stamp{
  position:absolute;left:2px;bottom:2px;display:grid;justify-items:center;gap:1px;
  padding:5px 10px;border:1.5px solid rgba(30,53,102,.42);border-radius:4px;
  transform:rotate(-7deg);opacity:.5;pointer-events:none;
  box-shadow:0 0 0 2.5px rgba(30,53,102,.10);
}
.rx__stamp b{font-size:.56rem;font-weight:800;letter-spacing:.1em;color:var(--ink-pen)}
.rx__stamp span{font-family:var(--mono);font-size:.46rem;letter-spacing:.09em;color:var(--ink-pen)}

@media (max-width:820px){
  .rxpad{grid-template-columns:1fr;gap:26px}
  .rxsheet:first-child,.rxsheet:last-child{transform:none}
  /* Straighten the backing papers too. A 1.7deg tilt on a sheet this tall adds
     ~13px of width on each side, which together with their offset was pushing
     past the page gutter and giving the whole document a 2px sideways scroll. */
  .rxsheet::before{transform:translate(-4px,4px)}
  .rxsheet::after{transform:translate(4px,7px)}
  .rx__head{grid-template-columns:auto 1fr;gap:10px}
  .rx__reg{grid-column:2;text-align:left;margin-top:2px}
  .rx__stamp{position:static;transform:rotate(-3deg);justify-self:start}
  .rx__signblock{justify-self:start;justify-items:start}
}


/* --------------------------------------------------- prescription motion -- */
/* A short sequence when the pad scrolls into view: the sheets settle, the script
   writes itself line by line, the signature is drawn, and the stamp comes down
   last with a little overshoot. Everything below is scoped to .is-live, which
   main.js only adds when motion is welcome — so with reduced motion, or with no
   observer at all, the finished prescription is simply already there. */

/* Sheets fall into place. Each keyframe ends on the resting tilt the sheet already
   has, so the animation lands exactly where the static layout would have put it. */
.rxpad.is-live .rxsheet:first-child{animation:rxDropL .72s var(--ease) both}
.rxpad.is-live .rxsheet:last-child {animation:rxDropR .72s var(--ease) .1s both}
@keyframes rxDropL{
  from{opacity:0;transform:translateY(-24px) rotate(-4.5deg)}
  to  {opacity:1;transform:translateY(0) rotate(-.5deg)}
}
@keyframes rxDropR{
  from{opacity:0;transform:translateY(-24px) rotate(4deg)}
  to  {opacity:1;transform:translateY(0) rotate(.4deg)}
}

/* The ℞ is struck before anything is written under it. */
.rxpad.is-live .rx__mark{opacity:0;animation:rxPop .4s var(--ease) .5s both}
@keyframes rxPop{from{opacity:0;transform:translateY(6px) scale(.9)}to{opacity:1;transform:none}}

/* Handwriting is revealed left to right, the way a pen lays it down. clip-path
   rather than width so the glyphs never reflow mid-stroke. */
.rxpad.is-live .rx__drug,
.rxpad.is-live .rx__dose,
.rxpad.is-live .rx__sign{clip-path:inset(0 100% 0 0)}
.rxpad.is-live .rx__drug{animation:rxWrite .42s var(--ease) both;animation-delay:calc(.62s + var(--i) * 70ms)}
.rxpad.is-live .rx__dose{animation:rxWrite .38s var(--ease) both;animation-delay:calc(.72s + var(--i) * 70ms)}
@keyframes rxWrite{to{clip-path:inset(0 0 0 0)}}

/* The number, the icon and the printed note arrive with their line but do not
   need writing — only the pen strokes get the reveal. */
.rxpad.is-live .rx__no,
.rxpad.is-live .rx__ico,
.rxpad.is-live .rx__note{opacity:0;animation:rxInk .34s var(--ease) both}
.rxpad.is-live .rx__no {animation-delay:calc(.58s + var(--i) * 70ms)}
.rxpad.is-live .rx__ico{animation-delay:calc(.60s + var(--i) * 70ms)}
.rxpad.is-live .rx__note{animation-delay:calc(.80s + var(--i) * 70ms)}
@keyframes rxInk{from{opacity:0}to{opacity:1}}

/* Signed, then stamped. The stamp overshoots and settles, which is what a stamp
   pressed by hand actually does. */
.rxpad.is-live .rx__sign{animation:rxWrite .55s var(--ease) 1.72s both}
.rxpad.is-live .rx__stamp{opacity:0;animation:rxStamp .42s cubic-bezier(.2,1.6,.4,1) 2.0s both}
@keyframes rxStamp{
  from{opacity:0;transform:rotate(-17deg) scale(1.55)}
  to  {opacity:.5;transform:rotate(-7deg) scale(1)}
}

/* Pick a sheet up to read it. */
.rxsheet{transition:transform .3s var(--ease)}
.rx{transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
.rxsheet:hover{z-index:3}
.rxsheet:hover .rx{
  transform:translateY(-7px);
  box-shadow:0 1px 0 #F6F3EB, 0 2px 0 #F0ECE2, 0 34px 60px rgba(13,24,34,.22);
}

/* ----------------------------------------------------------------- film -- */
/* A poster and a play button, not a live YouTube iframe. The embed only exists
   after someone asks for it, so the page costs nothing and sets no third-party
   cookie for visitors who never press play. */
/* Film and register share the row. The film keeps minmax(0,…) so a 16:9 poster
   cannot push the grid wider than the wrap and start a horizontal scroll. */
.sale__grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);
  gap:24px;align-items:stretch;margin-bottom:26px;
}

/* ------------------------------------------------------------ the write fan --
   One sale fanning into the three places it lands. The lane colours are the ones
   the suite section already names in prose — red at the counter, green on the
   shelf, slate in the back office — so this is that sentence drawn rather than a
   new palette invented for one panel. */
.wfan{
  display:flex;flex-direction:column;
  background:var(--deep-2);border:1px solid var(--deep-line);border-radius:var(--r-lg);
  padding:20px 18px 18px;
}

.wfan__top{
  align-self:center;display:flex;align-items:center;gap:8px;
  padding:7px 14px;border-radius:99px;
  background:rgba(255,255,255,.04);border:1px solid var(--deep-line);
  font:600 .76rem/1 var(--mono);letter-spacing:.04em;color:var(--deep-ink);white-space:nowrap;
}
.wfan__top b{
  display:grid;place-items:center;width:19px;height:19px;border-radius:50%;
  background:var(--red-hi);color:#fff;font-size:.7rem;
}

/* preserveAspectRatio="none" lets the branches stretch to whatever width the column
   settles at, so the three ends stay over the three lanes instead of drifting off
   them as the grid resizes. */
.wfan__split{display:block;width:100%;height:44px;margin:2px 0 -2px}
.wfan__split path{fill:none;stroke-width:1.5;stroke-linecap:round;vector-effect:non-scaling-stroke}
.wfan__split path{stroke:rgba(255,255,255,.22)}
.wfan__split .wfan__b1{stroke:var(--red-hi);opacity:.75}
.wfan__split .wfan__b2{stroke:var(--green);opacity:.7}
.wfan__split .wfan__b3{stroke:#7C93A8;opacity:.7}

.wfan__lanes{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(3,1fr);gap:10px;
  /* start, not stretch: a lane holding two rows should be the height of two rows.
     Stretching them to the card left three tall boxes mostly full of nothing. */
  align-items:start;
}

/* The tint is the lane's own colour at low alpha, and the top border is the same
   colour solid — so a lane is identifiable at a glance without a legend. */
.wfan__lane{
  padding:11px 9px;border-radius:11px;border:1px solid var(--deep-line);
  border-top-width:2px;background:rgba(255,255,255,.03);
  display:flex;flex-direction:column;gap:7px;min-width:0;
}
.wfan__lane--counter{border-top-color:var(--red-hi);background:rgba(251,44,35,.07)}
.wfan__lane--shelf  {border-top-color:var(--green); background:rgba(0,145,58,.09)}
.wfan__lane--office {border-top-color:#7C93A8;      background:rgba(124,147,168,.09)}

.wfan__where{
  font:600 .63rem/1.2 var(--sans);letter-spacing:.07em;text-transform:uppercase;
  color:var(--deep-mute);
  /* "At the counter" wraps at this width while the other two do not, which dropped
     its table names half a line below theirs. Two lines' worth for all three keeps
     the rows on one baseline. */
  min-height:2.4em;
}
.wfan__rows{display:flex;flex-direction:column;gap:5px;min-width:0}
/* Wrapping a table name mid-token would read as two names, so they shrink instead —
   stock_ledger is the widest and sets the floor. */
.wfan__rows b{
  font:600 .7rem/1.25 var(--mono);color:var(--deep-ink);
  overflow-wrap:anywhere;letter-spacing:-.02em;
}

.wfan__foot{
  /* auto rather than a fixed gap: the card stretches to the film's height, so this
     is what keeps the verdict on the bottom edge instead of floating mid-card. */
  margin-top:auto;padding-top:13px;border-top:1px solid var(--deep-line);
  font-size:.76rem;line-height:1.5;color:var(--deep-mute);
}
.wfan__chip{
  display:inline-block;margin-right:7px;padding:3px 8px;border-radius:6px;
  font:700 .66rem/1 var(--mono);letter-spacing:.1em;
  color:#7BE8A6;background:rgba(0,145,58,.16);border:1px solid rgba(123,232,166,.35);
}

@media (max-width:900px){
  .sale__grid{grid-template-columns:1fr;gap:18px}
}
/* Three lanes need three columns to be a fan at all; below this the branches would
   be drawing to nothing, so the drawing goes and the lanes stack. */
@media (max-width:430px){
  .wfan__split{display:none}
  .wfan__lanes{grid-template-columns:1fr}
}

.film{max-width:880px;border-radius:var(--r-xl);overflow:hidden;
  box-shadow:0 30px 64px rgba(0,0,0,.42), 0 3px 10px rgba(0,0,0,.3)}

.film__play{
  position:relative;display:block;width:100%;padding:0;border:0;cursor:pointer;
  background:#0B1620;line-height:0;
}
.film__poster{width:100%;height:auto;display:block;transition:transform .5s var(--ease),filter .3s var(--ease)}
.film__play:hover .film__poster{transform:scale(1.03);filter:brightness(1.05)}
.film__play:focus-visible{outline:3px solid var(--red-hi);outline-offset:3px}

.film__btn{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  display:grid;place-items:center;width:76px;height:76px;border-radius:50%;
  background:var(--red);color:#fff;padding-left:4px;
  box-shadow:0 12px 34px rgba(224,30,20,.5);
  transition:transform .24s var(--ease),background .24s var(--ease);
}
.film__play:hover .film__btn{transform:translate(-50%,-50%) scale(1.09);background:var(--red-hi)}

.film__meta{
  position:absolute;left:0;right:0;bottom:0;padding:44px 22px 18px;text-align:left;
  background:linear-gradient(to top, rgba(6,13,20,.88), transparent);
  display:grid;gap:2px;line-height:1.4;
}
.film__meta b{font-family:var(--display);font-size:1.02rem;color:#fff}
.film__meta span{font-size:.82rem;color:rgba(255,255,255,.76)}

/* Local-preview only: shown when the page is opened off disk, where YouTube
   refuses to configure a player at all. */
.film__note{
  position:absolute;left:16px;right:16px;bottom:16px;z-index:2;
  padding:11px 15px;border-radius:var(--r);
  background:rgba(10,20,29,.92);color:#FFD9D6;
  font-size:.84rem;line-height:1.45;text-align:left;
}

/* Once playing, the iframe replaces the button and keeps the same box. */
.film iframe{display:block;width:100%;aspect-ratio:16/9;border:0}

@media (max-width:560px){
  .film__btn{width:60px;height:60px}
  .film__meta{padding:36px 16px 14px}
}

/* ---------------------------------------------------------- the counter -- */
/* A tax invoice, drawn in markup. It replaced a screenshot gallery: a screenshot
   on a marketing page is a small blurry rectangle nobody reads, and the demo is
   where the real interface belongs. An invoice is the one artefact every pharmacist
   already recognises — and it is literally what this software produces. */
.counter{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,380px);
  gap:clamp(34px,5vw,72px);align-items:center;
}
.counter__pts{list-style:none;margin:26px 0 0;padding:0;display:grid;gap:14px}
.counter__pts li{
  position:relative;padding-left:26px;font-size:.97rem;color:var(--muted);line-height:1.55;
}
.counter__pts b{color:var(--ink);font-weight:800}
.counter__pts li::before{
  content:"";position:absolute;left:0;top:.5em;width:9px;height:9px;border-radius:50%;
  background:var(--red);box-shadow:0 0 0 4px var(--red-soft);
}
.counter__actions{margin-top:30px}
.counter__aside{margin-top:14px;font-size:.86rem;color:var(--muted)}

.counter__paper{display:flex;justify-content:center;perspective:1200px}

.rc{
  position:relative;width:100%;max-width:360px;
  background:#fff;color:#1A2833;
  font-family:var(--mono);font-size:.76rem;line-height:1.5;
  padding:26px 24px 34px;
  box-shadow:0 24px 60px rgba(13,24,34,.18), 0 2px 6px rgba(13,24,34,.06);
  transform:rotate(-1.1deg);
}
/* Torn bottom edge — two gradients meeting as triangles. A real till receipt is
   never cut straight, and that detail is most of why this reads as paper. */
.rc::after{
  content:"";position:absolute;left:0;right:0;bottom:-13px;height:14px;
  background:
    linear-gradient(-45deg, transparent 9px, #fff 0) left / 18px 14px repeat-x;
}
/* A hairline of print texture down each edge, so the paper is not a flat rectangle. */
.rc::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg, rgba(13,24,34,.05), transparent 8px, transparent calc(100% - 8px), rgba(13,24,34,.05));
}

.rc__line{opacity:1}
/* Printing: each row lands a beat after the one above it. Only applied once the
   receipt is in view, so it prints when you arrive rather than before. */
.rc.is-printing .rc__line{
  opacity:0;transform:translateY(-6px);
  animation:rcPrint .34s var(--ease) forwards;
  animation-delay:calc(var(--i) * 65ms);
}
@keyframes rcPrint{to{opacity:1;transform:none}}

.rc__h{text-align:center;font-weight:600;font-size:.95rem;letter-spacing:.06em}
.rc__sub{text-align:center;color:#61748A;font-size:.68rem;letter-spacing:.04em}
.rc__k{text-align:center;font-weight:600;letter-spacing:.18em;font-size:.7rem;margin:2px 0}
.rc__rule{border-top:1px dashed #C6D2DC;margin:9px 0}

.rc__kv{display:flex;justify-content:space-between;gap:12px;color:#41525F}
.rc__kv b{font-weight:600;color:#1A2833}

.rc__item{margin:7px 0}
.rc__name{font-weight:600}
.rc__meta{color:#7C8B98;font-size:.68rem}
.rc__amt{display:flex;justify-content:space-between;gap:12px;color:#41525F}
.rc__amt b{font-weight:600;color:#1A2833}

.rc__tot{
  display:flex;justify-content:space-between;gap:12px;
  font-size:.94rem;font-weight:600;letter-spacing:.02em;margin:3px 0;
}
.rc__note{
  margin-top:4px;text-align:center;font-size:.66rem;line-height:1.45;color:#2E7D4F;
}
.rc__stamp{
  margin-top:12px;text-align:center;font-size:.62rem;font-weight:600;letter-spacing:.16em;
  color:var(--red);border:1.5px solid var(--red);border-radius:6px;padding:6px 4px;
  transform:rotate(-2deg);
}

@media (max-width:900px){
  .counter{grid-template-columns:1fr;gap:38px}
  .counter__paper{order:-1}
  .rc{transform:none;max-width:340px}
}

/* -------------------------------------------------------------- the rig -- */
/* Three products, three devices, staged the way each is actually used: the
   counter machine, head office in a browser, the consulting room. Every screen
   is a real capture — Nucleus and KLINIK come from tools/capture-siblings.mjs,
   not from anything drawn to look like them. */
.rig{
  position:relative;height:clamp(360px,42vw,540px);margin-bottom:clamp(56px,7vw,88px);
  isolation:isolate;
}

.rig__blob{
  position:absolute;left:50%;top:4%;width:min(46%,420px);aspect-ratio:1;
  transform:translateX(-42%);border-radius:50%;
  background:radial-gradient(circle at 40% 35%, rgba(224,30,20,.14), rgba(224,30,20,.04) 60%, transparent 72%);
  z-index:-1;
}
.rig__dots{
  position:absolute;width:clamp(90px,11vw,140px);height:clamp(70px,9vw,110px);z-index:-1;
  background-image:radial-gradient(currentColor 1.7px, transparent 1.8px);
  background-size:15px 15px;color:#C9D6E2;opacity:.75;
}
.rig__dots--a{left:1%;top:46%}
.rig__dots--b{right:2%;top:8%;color:#F0B7B2}

.dev{margin:0;position:absolute}
.dev__screen{
  overflow:hidden;background:#0F1D28;
  border:1px solid rgba(13,24,34,.14);
  box-shadow:0 26px 60px rgba(13,24,34,.20), 0 3px 10px rgba(13,24,34,.10);
}
.dev__screen img{width:100%;height:100%;object-fit:cover;object-position:top left;display:block}

/* desktop, centre-back: the counter machine */
.dev--desk{left:50%;top:0;width:min(52%,560px);transform:translateX(-50%);z-index:2}
.dev--desk .dev__screen{border-radius:12px;padding:9px;aspect-ratio:16/10}
.dev--desk .dev__stand{
  display:block;width:16%;height:34px;margin:0 auto;
  background:linear-gradient(180deg,#D5DEE6,#B9C6D2);
}
.dev--desk .dev__foot{
  display:block;width:38%;height:9px;margin:0 auto;border-radius:0 0 8px 8px;
  background:linear-gradient(180deg,#C3CFDA,#9FB0BF);
}

/* laptop, front-left: head office */
.dev--lap{left:0;bottom:2%;width:min(46%,470px);z-index:3}
.dev--lap .dev__screen{border-radius:10px;padding:8px;aspect-ratio:16/10}
.dev--lap .dev__base{
  display:block;width:112%;height:13px;margin:0 -6% ;border-radius:0 0 10px 10px;
  background:linear-gradient(180deg,#DCE4EC,#AEBDCA);
  box-shadow:0 8px 18px rgba(13,24,34,.16);
}

/* tablet, front-right: the consulting room */
.dev--tab{right:1%;bottom:8%;width:min(23%,215px);z-index:4}
.dev--tab .dev__screen{border-radius:16px;padding:7px;aspect-ratio:3/4}

/* Floating labels, the one part of the composition that carries words. */
.tag{
  position:absolute;z-index:5;display:grid;gap:1px;
  background:#fff;border:1px solid var(--line);border-radius:14px;
  padding:11px 16px;box-shadow:0 14px 30px rgba(13,24,34,.13);
}
.tag b{font-size:.92rem;color:var(--ink);letter-spacing:-.012em}
.tag span{font-size:.76rem;color:var(--muted)}
.tag--desk{left:4%;top:6%}
.tag--lap {left:26%;bottom:-2%}
.tag--tab {right:0;top:26%}

/* The composition is decoration below the tablet's readable size — the three
   product blocks underneath carry the same information in words. */
@media (max-width:820px){
  .rig{height:auto;display:grid;gap:16px;margin-bottom:44px}
  .dev,.tag{position:static}
  .dev--desk,.dev--lap,.dev--tab{width:100%;transform:none}
  .dev--tab .dev__screen{aspect-ratio:16/10}
  .dev--desk .dev__stand,.dev--desk .dev__foot,.dev--lap .dev__base{display:none}
  .rig__blob,.rig__dots{display:none}
  .tag{justify-self:start;box-shadow:none;padding:8px 13px}
}

/* ------------------------------------------------------------- products -- */
/* Three full-width blocks that alternate sides, rather than three equal cards.
   Each product gets room for a headline, four capabilities and its own visual —
   and the alternation is what keeps six screens of page from reading as one
   endless column of centred grids. */
.prods{display:grid;gap:clamp(56px,7vw,96px)}

.prod{
  display:grid;grid-template-columns:minmax(0,1.06fr) minmax(0,1fr);
  gap:clamp(30px,4.5vw,64px);align-items:center;
}
.prod--flip .prod__visual{order:-1}

.prod__kicker{
  font-family:var(--mono);font-size:0.75rem;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);margin-bottom:14px;
}
.prod--lead .prod__kicker{color:var(--red)}
.prod__copy h3{font-size:clamp(1.6rem,3vw,2.3rem);line-height:1.14;margin-bottom:16px}
.prod__body{font-size:1.02rem;color:var(--muted);max-width:52ch}

.prod__list{
  list-style:none;margin:22px 0 0;padding:22px 0 0;
  border-top:1px solid var(--line);display:grid;gap:11px;
}
.prod__list li{position:relative;padding-left:26px;font-size:.94rem;color:var(--ink-2)}
.prod__list li::before{
  content:"";position:absolute;left:0;top:.34em;width:15px;height:15px;border-radius:50%;
  background:var(--green-soft);
}
.prod__list li::after{
  content:"";position:absolute;left:4.8px;top:.56em;width:4px;height:7.5px;
  border:solid var(--green);border-width:0 2px 2px 0;transform:rotate(42deg);
}
.prod--lead .prod__list li::before{background:var(--red-soft)}
.prod--lead .prod__list li::after{border-color:var(--red)}

.prod__cta{
  display:inline-flex;align-items:center;gap:8px;margin-top:24px;
  font-weight:800;font-size:.95rem;color:var(--red);
}
.prod__cta svg{transition:transform .22s var(--ease)}
.prod__cta:hover svg{transform:translateX(4px)}

.prod__photo{
  margin:0;border-radius:var(--r-xl);overflow:hidden;
  border:1px solid var(--line);box-shadow:var(--sh-1);
}
.prod__photo img{width:100%;height:auto;display:block}
.prod__visual .frame{margin:0}

/* Nucleus has no screenshot in this repo, and passing a Ranbix screen off as one
   would misrepresent what you'd actually see. A diagram states the shape of the
   thing — many stores, one console — without pretending to be a product shot. */
.hub{width:100%;height:auto;display:block}
.hub__spokes path{stroke:var(--line);stroke-width:2;fill:none}
.hub__store rect{fill:#fff;stroke:var(--line);stroke-width:1.5}
.hub__label text{
  font-family:var(--mono);font-size:13px;font-weight:600;fill:var(--muted);
  text-anchor:middle;
}
.hub__core{fill:var(--red);}
.hub__core-label{
  font-family:var(--mono);font-size:15px;font-weight:600;letter-spacing:.12em;
  fill:#fff;text-anchor:middle;
}

@media (max-width:860px){
  .prod{grid-template-columns:1fr;gap:28px}
  /* The visual leads on every block once stacked — alternating order only reads as
     rhythm side by side; in one column it just looks inconsistent. */
  .prod--flip .prod__visual{order:0}
  .prod__visual{order:-1}
}

/* ------------------------------------------------------------------ chat -- */
/* The chat panel behind the floating launcher. Ranbix already sells "talk to us on
   WhatsApp", so the questions are asked the way a buyer would actually ask them.
   These rules are shared with .dock, which is the only thing using them now. */
.chat__bar{
  display:flex;align-items:center;gap:12px;padding:14px 20px;
  background:var(--deep);border-bottom:1px solid var(--deep-line);
}
.chat__av{width:42px;height:42px;border-radius:50%;object-fit:cover;flex:0 0 auto}
.chat__who b{display:block;font-size:.95rem;color:#fff;letter-spacing:-.012em}
.chat__who>span{display:flex;align-items:center;gap:7px;font-size:.78rem;color:var(--deep-mute)}
.chat__dot{width:7px;height:7px;border-radius:50%;background:#3DD68C;flex:0 0 auto}

/* A ceiling rather than a fixed height: short threads sit at their own size, long
   ones scroll instead of pushing the page around as answers arrive. */
.chat__thread{
  list-style:none;margin:0;padding:22px 20px;display:grid;gap:14px;
  max-height:clamp(300px,44vh,430px);overflow-y:auto;scroll-behavior:smooth;
  background:
    radial-gradient(circle at 20% 30%, rgba(13,24,34,.022) 1.4px, transparent 1.5px) 0 0/22px 22px,
    var(--soft);
}

.msg{display:grid;gap:9px;align-items:end;max-width:86%}
.msg__b{
  padding:11px 15px;font-size:.93rem;line-height:1.55;border-radius:16px;
  box-shadow:0 1px 2px rgba(13,24,34,.06);
}
.msg--in{grid-template-columns:30px minmax(0,1fr);justify-self:start}
.msg--in .msg__av{width:30px;height:30px;border-radius:50%;object-fit:cover;align-self:end}
.msg--in .msg__b{background:#fff;color:var(--ink-2);border-bottom-left-radius:5px}
.msg--out{justify-self:end;justify-items:end}
.msg--out .msg__b{background:var(--red);color:#fff;border-bottom-right-radius:5px;font-weight:600}

/* Arriving messages come in from below, the way a real thread behaves. */
.msg.is-new{animation:msgIn .3s var(--ease) both}
@keyframes msgIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

.msg--typing .msg__b{display:flex;gap:5px;padding:14px 16px}
.msg--typing i{
  width:7px;height:7px;border-radius:50%;background:#B7C4D0;
  animation:typing 1s ease-in-out infinite;
}
.msg--typing i:nth-child(2){animation-delay:.16s}
.msg--typing i:nth-child(3){animation-delay:.32s}
@keyframes typing{0%,60%,100%{opacity:.35;transform:translateY(0)}30%{opacity:1;transform:translateY(-4px)}}

.chat__asks{
  display:flex;flex-wrap:wrap;gap:9px;padding:16px 20px;
  border-top:1px solid var(--line);background:#fff;
}
.ask{
  font-family:inherit;font-size:.86rem;font-weight:600;color:var(--ink-2);
  background:#fff;border:1.5px solid var(--line);border-radius:999px;
  padding:9px 16px;cursor:pointer;text-align:left;
  transition:all .2s var(--ease);
}
.ask:hover{border-color:var(--ink-2);color:var(--ink);transform:translateY(-1px)}
.ask.is-asked{opacity:.42;pointer-events:none;text-decoration:line-through}

.chat__foot{padding:0 20px 18px;font-size:.86rem;color:var(--muted);background:#fff}
.chat__foot a{color:var(--red);font-weight:700}
.chat__foot a:hover{text-decoration:underline}

@media (max-width:560px){
  .msg{max-width:94%}
  .ask{font-size:.8rem;padding:8px 13px}
}

/* ------------------------------------------------------------------ cta -- */
.cta{
  background:
    radial-gradient(760px 420px at 50% -10%, rgba(251,44,35,.24), transparent 64%),
    linear-gradient(180deg,var(--deep-2),var(--deep));
  color:var(--deep-mute);text-align:center;
  padding:clamp(72px,9vw,116px) 0;
}
.cta__in{max-width:720px}
.cta h2{color:#fff;margin-bottom:18px}
.cta p{font-size:1.05rem}
.cta__actions{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;margin-top:34px}

/* ---------------------------------------------------------------- legal -- */
/* Long-form reading, so the measure is tighter than the marketing sections and
   the vertical rhythm is bigger. Nothing here is used on index.html. */
.legal{padding:clamp(48px,6vw,76px) 0 clamp(64px,8vw,104px)}

.legal__crumb{
  display:flex;align-items:center;gap:10px;margin-bottom:26px;
  font-size:.84rem;font-weight:700;color:var(--muted);
}
.legal__crumb a{color:var(--red)}
.legal__crumb a:hover{text-decoration:underline}
.legal__crumb span[aria-hidden]{color:var(--line)}

.legal__head{margin-bottom:clamp(32px,4vw,46px);padding-bottom:26px;border-bottom:1px solid var(--line)}
.legal__head h1{font-size:clamp(2rem,4vw,2.9rem);margin-bottom:16px}
.legal__lede{font-size:1.06rem;color:var(--muted);max-width:60ch}
.legal__meta{
  display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:22px;
  font-family:var(--mono);font-size:.74rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);
}
.legal__meta span{display:inline-flex;align-items:center;gap:8px}
.legal__meta span+span::before{content:"";width:4px;height:4px;border-radius:50%;background:var(--line)}

.legal__body h2{
  font-size:1.12rem;margin:38px 0 12px;
  padding-top:20px;border-top:1px solid var(--line);
}
.legal__body h2:first-child{margin-top:0;padding-top:0;border-top:0}
.legal__body p{margin-bottom:14px;color:var(--ink-2);font-size:1rem}
.legal__body b{color:var(--ink)}
.legal__body a{color:var(--red);font-weight:700}
.legal__body a:hover{text-decoration:underline}
.legal__body ul{margin:0 0 16px;padding-left:22px;display:grid;gap:9px}
.legal__body li{color:var(--ink-2)}
.legal__body li::marker{color:var(--red)}
.legal__addr{
  font-style:normal;padding:16px 20px;border-radius:var(--r);
  background:var(--soft);border:1px solid var(--line);
  font-size:.95rem;line-height:1.6;
}

.legal__also{
  display:flex;flex-wrap:wrap;align-items:center;gap:14px;
  margin-top:48px;padding-top:26px;border-top:1px solid var(--line);
  font-size:.9rem;
}
.legal__also span{font-weight:800;color:var(--ink)}
.legal__also a{
  padding:9px 16px;border:1.5px solid var(--line);border-radius:999px;
  font-weight:700;color:var(--ink-2);transition:all .2s var(--ease);
}
.legal__also a:hover{border-color:var(--ink);color:var(--ink)}

/* The reduced legal nav has no link list to push the buttons right. */
.nav__cta--legal{margin-left:auto}
@media (max-width:900px){ .nav__cta--legal{display:flex} }
@media (max-width:560px){
  .nav__cta--legal .btn{padding:10px 14px;font-size:.82rem}
  .legal__body h2{font-size:1.05rem}
}

/* --------------------------------------------------------------- pricing -- */
/* Lives here rather than in a <style> block on pricing.html, so the site keeps
   one stylesheet and the price layer can reach the same tokens as everything
   else — the plan cards are the .prod cards' cousins, not a separate design. */

/* Visually hidden but read aloud. The module table's <caption> is the only thing
   that explains what its columns mean to a screen reader, and it would be noise
   above a table that already carries a section heading. */
.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;
}

.phero{padding:clamp(46px,6vw,78px) 0 clamp(34px,4vw,48px);text-align:center;
  background:linear-gradient(180deg,#fff,var(--soft))}
.phero__in{display:flex;flex-direction:column;align-items:center}
/* The home page h1 is set to fill half a split hero. Here it sits over a centred
   measure and the top of the scale is far too loud for it. */
.phero h1{font-size:clamp(2.1rem,4.4vw,3.3rem);margin-top:18px}
.phero__lede{margin-top:20px;max-width:62ch;font-size:1.05rem;color:var(--muted)}

/* --- billing term switch --- */
.term{
  display:inline-flex;align-items:center;margin-top:32px;padding:5px;
  background:#fff;border:1px solid var(--line);border-radius:999px;box-shadow:var(--sh-1);
}
.term__btn{
  font:inherit;font-weight:700;font-size:.9rem;white-space:nowrap;cursor:pointer;
  padding:11px 22px;border:0;border-radius:999px;background:none;color:var(--muted);
  transition:background .2s var(--ease),color .2s var(--ease);
}
.term__btn[aria-pressed="true"]{background:var(--ink);color:#fff}
.term__save{
  display:inline-block;margin-left:8px;padding:3px 9px;border-radius:999px;
  font-size:.66rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  background:var(--green-soft);color:var(--green-deep);
}
.term__btn[aria-pressed="true"] .term__save{background:rgba(255,255,255,.16);color:#fff}

/* --- plan cards --- */
.sec--plans{padding-top:clamp(34px,4vw,52px)}
.plans{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;align-items:start}
.plan{
  display:flex;flex-direction:column;height:100%;position:relative;
  padding:28px 22px;background:var(--canvas);
  border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1);
}
.plan--pop{border-color:var(--red);box-shadow:0 18px 46px rgba(224,30,20,.13)}
.plan__flag{
  position:absolute;top:-12px;left:50%;transform:translateX(-50%);white-space:nowrap;
  padding:5px 14px;border-radius:999px;background:var(--red);color:#fff;
  font-size:.63rem;font-weight:800;letter-spacing:.13em;text-transform:uppercase;
}
.plan h2{font-size:1.3rem;margin-bottom:6px}
/* min-height so the four price rows land on one line whatever the blurb runs to. */
.plan__who{font-size:.85rem;color:var(--muted);line-height:1.4;min-height:3.4em}
.plan__price{display:flex;align-items:baseline;gap:2px;margin:20px 0 5px}
.plan__cur{font-size:1.15rem;font-weight:700;color:var(--ink-2)}
/* tabular-nums so 200 → 349 does not shuffle the row sideways as the term flips. */
.plan__amt{
  font-family:var(--display);font-size:2.5rem;font-weight:800;line-height:1;
  letter-spacing:-.03em;color:var(--ink);font-variant-numeric:tabular-nums;
}
.plan__amt--word{font-size:2rem}
.plan__per{margin-left:4px;font-size:.82rem;font-weight:600;color:var(--muted)}
.plan__billed{font-size:.79rem;color:var(--muted);min-height:2.6em}
.plan__billed b{color:var(--ink)}
.plan__billed s{opacity:.55;margin-right:5px}
.plan__cta{justify-content:center;margin:20px 0;width:100%}
.plan__inc{
  padding-bottom:11px;margin-bottom:15px;border-bottom:1px solid var(--line);
  font-size:.7rem;font-weight:800;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);
}
.plan__feat{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.plan__feat li{position:relative;padding-left:26px;font-size:.86rem;line-height:1.45;color:var(--ink-2)}
.plan__feat li::before{
  content:"";position:absolute;left:0;top:.32em;width:16px;height:16px;border-radius:50%;
  background:var(--green-soft);box-shadow:inset 0 0 0 1.5px rgba(0,145,58,.3);
}
.plan__feat li::after{
  content:"";position:absolute;left:5.4px;top:.56em;width:4.5px;height:8px;
  border:solid var(--green);border-width:0 2px 2px 0;transform:rotate(42deg);
}
/* Roadmap rows lose the tick entirely. A greyed tick still reads as "shipped" at a
   glance, which is the one thing these rows must not do. */
.plan__feat li.is-soon{color:var(--muted)}
.plan__feat li.is-soon::before{background:var(--soft);box-shadow:inset 0 0 0 1.5px var(--line)}
.plan__feat li.is-soon::after{
  content:"";left:7.4px;top:.42em;width:1.6px;height:8px;
  border:0;background:#9FB0C0;border-radius:1px;transform:none;
}
.tag-soon{
  margin-left:6px;padding:2px 7px;border-radius:5px;white-space:nowrap;
  background:var(--soft);border:1px solid var(--line);color:var(--muted);
  font-size:.6rem;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
}

/* --- modules × cost table --- */
/* No overflow here at desktop widths, deliberately. position:sticky resolves against
   the nearest scroll container, so wrapping the table in overflow-x:auto would peg the
   column heads to a box that never scrolls vertically — they would slide away with the
   page and the plan names would be gone by row six, which is exactly when a reader
   needs them. The scroll container is switched on below 900px, where the table really
   does have to scroll sideways and a stuck header matters less than fitting at all. */
.mods{background:var(--canvas);border:1px solid var(--line);border-radius:var(--r-lg)}
.modtab{width:100%;border-collapse:collapse;font-size:.9rem;min-width:760px}
.modtab th,.modtab td{padding:13px 16px;text-align:left;border-bottom:1px solid var(--line)}
.modtab tbody tr:last-child th,.modtab tbody tr:last-child td{border-bottom:0}
/* top:76px clears the sticky nav, which is exactly that tall. */
.modtab thead th{
  position:sticky;top:76px;z-index:2;vertical-align:bottom;
  background:var(--canvas);border-bottom:2px solid var(--line);
}
/* The wrapper cannot clip to its own radius without becoming a scroll container, so
   the corners are rounded on the cells that sit in them instead. */
.modtab thead th:first-child{
  border-top-left-radius:var(--r-lg);
  font-size:.7rem;font-weight:800;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);
}
.modtab thead th:last-child{border-top-right-radius:var(--r-lg)}
.modtab th:not(:first-child),.modtab td:not(:first-child){text-align:center;width:14%}
.modtab__plan{display:block;font-family:var(--display);font-weight:800;font-size:.98rem;color:var(--ink)}
.modtab__cost{
  display:block;margin-top:4px;font-family:var(--mono);font-size:.74rem;color:var(--muted);
  font-variant-numeric:tabular-nums;
}
.modtab__cost b{font-size:.86rem;font-weight:600;color:var(--ink-2)}
/* Laid out inline, not with display:flex — flex on a <th> destroys the table box, and
   the row rules stop short at the label's content edge instead of crossing the row. */
.modtab tbody th{font-weight:600;color:var(--ink);vertical-align:middle}
/* The module marks are stroked, not filled — same as everywhere else they appear. */
.modtab__ico{
  display:inline-grid;place-items:center;width:26px;height:26px;
  margin-right:10px;vertical-align:-8px;border-radius:8px;
  background:var(--soft);color:var(--muted);
}
.modtab__ico svg{fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.modtab tbody tr:hover td,.modtab tbody tr:hover th{background:var(--soft)}
.modtab .y{color:var(--green-deep);font-weight:700}
.modtab .n{color:#A8B6C4}

/* Group rows carry the site's counter/shelf/office colour language, so a module's
   band here matches the band it sits in on the prescription. */
.modtab__grp td{
  background:var(--ink);color:#fff;padding:9px 16px;
  font-size:.68rem;font-weight:800;letter-spacing:.13em;text-transform:uppercase;
}
.modtab__grp--counter td{background:var(--red)}
.modtab__grp--shelf td{background:var(--green-deep)}
.modtab__grp--office td{background:var(--ink-2)}
.modtab__grp:hover td{background:inherit}

/* --- footnotes --- */
.pnotes{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));gap:18px;margin-top:30px}
.pnote{
  padding:22px 24px;background:var(--canvas);border:1px solid var(--line);
  border-left:3px solid var(--green);border-radius:var(--r);
}
.pnote--red{border-left-color:var(--red)}
.pnote h3{font-size:.98rem;margin-bottom:8px}
.pnote p{font-size:.88rem;color:var(--muted)}

@media (max-width:1080px){
  .plans{grid-template-columns:repeat(2,1fr)}
  /* Two-up puts the flagged card on the right of row one, where a -12px badge would
     be clipped by nothing — but the row gap is only 18px, so it still needs room. */
  .plans{row-gap:28px}
}
.mods__hint{
  display:none;margin:0 0 10px;font-size:.8rem;font-weight:600;color:var(--muted);
}

@media (max-width:900px){
  /* Below this the table has to scroll sideways, so it becomes a scroll container —
     which costs the stuck header, since sticky then resolves against this box. The
     trade is worth it here: fitting on the screen beats a header that stays put. */
  .mods{overflow-x:auto}
  .modtab thead th{position:static}
  .modtab thead th:first-child,.modtab thead th:last-child{border-radius:0}
  .mods__hint{display:block}
}
@media (max-width:620px){
  /* At 760px wide the module column alone filled a phone screen, so the table showed
     fourteen module names and not one price — which is the opposite of the point.
     Narrower columns put a full plan on screen with the next one half-visible, and a
     half-visible column is its own invitation to swipe. */
  .modtab{min-width:560px;font-size:.84rem}
  .modtab th,.modtab td{padding:11px 10px}
  .modtab th:not(:first-child),.modtab td:not(:first-child){width:17%}
  .modtab__ico{width:22px;height:22px;margin-right:8px;vertical-align:-6px;border-radius:6px}
  .modtab__ico svg{width:13px;height:13px}
  /* Hanging indent: the icon is an inline box on the first line, so a long label's
     second line would otherwise start under the icon rather than under the text.
     -30px is the icon's 22px plus its 8px margin. */
  .modtab tbody th{padding-left:40px;text-indent:-30px}
}
@media (max-width:620px){
  .plans{grid-template-columns:1fr}
  .term{width:100%;justify-content:center}
  .term__btn{padding:11px 14px;font-size:.84rem}
  .term__save{margin-left:6px;padding:3px 7px}
  .plan__who{min-height:0}
  .plan__billed{min-height:0}
}

/* --------------------------------------------------------------- footer -- */
.foot{background:var(--deep);color:var(--deep-mute);border-top:1px solid var(--deep-line)}
.foot__in{
  display:grid;grid-template-columns:1.7fr repeat(4,minmax(0,1fr));gap:30px;
  align-items:start;
  padding-top:clamp(52px,6vw,74px);padding-bottom:44px;
}
.foot__brand img{height:46px;width:auto;margin-bottom:16px}
.foot__brand p{font-size:.92rem;max-width:34ch;line-height:1.7}

.foot__social{display:flex;gap:10px;list-style:none;margin:22px 0 0;padding:0}
.foot__social a{
  display:grid;place-items:center;width:38px;height:38px;border-radius:50%;
  color:var(--deep-mute);border:1px solid var(--deep-line);
  transition:color .2s var(--ease),border-color .2s var(--ease),
             background .2s var(--ease),transform .2s var(--ease);
}
/* fill:currentColor — the marks inherit the link colour, so there is one hover
   state to maintain rather than three tinted icon files. */
.foot__social svg{width:17px;height:17px;fill:currentColor}
.foot__social a:hover{
  color:#fff;border-color:rgba(255,255,255,.34);
  background:rgba(255,255,255,.07);transform:translateY(-2px);
}
.foot__col{display:flex;flex-direction:column;gap:10px}
.foot__col h3{color:#fff;font-size:.95rem;margin-bottom:6px}
.foot__col a{font-size:.92rem;transition:color .18s}
.foot__col a:hover{color:#fff}


.foot__base{
  display:flex;flex-wrap:wrap;gap:14px;justify-content:space-between;align-items:center;
  padding-top:22px;padding-bottom:30px;border-top:1px solid var(--deep-line);
  font-size:.85rem;
}
.foot__by{display:inline-flex;align-items:center;gap:8px}
.foot__by img{height:20px;width:20px;border-radius:5px}

/* ---------------------------------------------------------------- modal -- */
/* The <dialog> element is the sizing box; .modal__card is the visible surface.
   Keeping padding off the dialog means anything outside the card is backdrop,
   which is what lets the click-outside-to-close test in main.js be a simple
   `e.target === modal`. */
.modal{
  border:0;padding:0;background:transparent;color:var(--ink-2);
  width:min(580px,calc(100vw - 32px));
  max-height:calc(100dvh - 40px);
  overflow:visible;
}
.modal::backdrop{background:rgba(6,13,20,.62);backdrop-filter:blur(3px)}
.modal[open]{animation:modalIn .26s var(--ease) both}
@keyframes modalIn{
  from{opacity:0;transform:translateY(14px) scale(.985)}
  to{opacity:1;transform:none}
}

.modal__card{
  position:relative;background:#fff;border-radius:var(--r-xl);
  padding:34px 36px 32px;box-shadow:var(--sh-2);
  max-height:calc(100dvh - 40px);overflow-y:auto;
}
/* The section h2 scale is built for a full-width band and is far too large inside
   a 580px card. */
.modal h2{font-size:clamp(1.35rem,3.4vw,1.62rem);margin-bottom:12px}
.modal__sub{font-size:.95rem;color:var(--muted)}
.modal__sub a{color:var(--red);font-weight:700}

.modal__x{
  position:absolute;top:15px;right:15px;z-index:1;
  display:grid;place-items:center;width:36px;height:36px;border-radius:50%;
  background:#fff;border:1px solid var(--line);color:var(--muted);cursor:pointer;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease);
}
.modal__x svg{width:16px;height:16px}
.modal__x:hover{background:var(--soft);color:var(--ink);border-color:#D2DCE6}

.fields{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:24px}
.field{display:flex;flex-direction:column;gap:6px;min-width:0}
.field--wide{grid-column:1/-1}
.field label{font-size:.8rem;font-weight:700;color:var(--ink)}
.field label span{color:var(--red)}
.field input,.field select,.field textarea{
  font-family:inherit;font-size:.94rem;color:var(--ink);width:100%;
  background:#fff;border:1.5px solid var(--line);border-radius:var(--r);padding:11px 13px;
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease);
}
.field textarea{resize:vertical;min-height:84px;line-height:1.5}
.field select{appearance:none;cursor:pointer;
  /* Chevron as a data: URI — an external asset would be blocked on a strict CSP
     and is not worth a network round trip for one 7px mark. */
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%2361748A' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 13px center;background-size:11px;
  padding-right:34px;
}
/* Replaces the global focus ring rather than removing it — drawn as a halo so it
   follows the input's own radius instead of boxing it.
   Deliberately NOT brand red: red is the error colour three lines down, and when
   both used it, a freshly-opened form showed its focused first field looking exactly
   like a field that had already been rejected. */
.field input:focus,.field select:focus,.field textarea:focus{
  outline:0;border-color:var(--ink-2);box-shadow:0 0 0 3px rgba(42,59,74,.13);
}
.field.is-bad input,.field.is-bad select,.field.is-bad textarea{border-color:var(--red)}
/* Focusing a rejected field must not clear the signal that it is still wrong. */
.field.is-bad input:focus,.field.is-bad select:focus,.field.is-bad textarea:focus{
  border-color:var(--red);box-shadow:0 0 0 3px rgba(224,30,20,.15);
}

/* Off-screen rather than display:none — a bot reading the DOM should still see a
   fillable field, which is the whole point of the trap. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.modal__err{
  margin-top:16px;padding:11px 14px;border-radius:var(--r);
  background:var(--red-soft);border:1px solid rgba(224,30,20,.22);
  font-size:.88rem;font-weight:600;color:#A8140C;
}
.modal__err[hidden]{display:none}

/* The OTP step. One field, so it gets the room the six digits deserve — wide
   tracking and a tabular face, which is what makes a mistyped code obvious at a
   glance rather than after the server says no. Width is capped in ch so the box
   ends where the code does and does not read as a six-digit answer in a field
   built for a sentence. */
.field--code{margin-top:24px;max-width:15ch}
.field--code input{
  font-variant-numeric:tabular-nums;font-size:1.5rem;font-weight:700;
  letter-spacing:.34em;text-align:center;padding:13px 0 13px .34em;
}
.field--code input::placeholder{letter-spacing:.2em;font-weight:600}

/* A button that has to read as a link: Resend and Change number are actions, not
   navigation, so they must not be anchors — but they sit in a line of prose and
   would look absurd as two more solid buttons. */
.linkish{
  font:inherit;font-weight:700;color:var(--red);
  background:none;border:0;padding:0;cursor:pointer;text-decoration:underline;
  text-underline-offset:3px;text-decoration-thickness:1.5px;
}
.linkish:hover{text-decoration-thickness:2.5px}
.linkish[disabled]{color:var(--muted);cursor:default;text-decoration:none}
.modal__dot{margin:0 7px;color:var(--line)}

.modal__actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px;margin-top:22px}
.modal__actions .btn{padding:14px 26px}
.modal__alt{font-size:.86rem;color:var(--muted)}
.modal__alt a{color:var(--red);font-weight:700}
#demoSubmit[disabled],#otpSubmit[disabled]{opacity:.6;cursor:progress;transform:none;box-shadow:none}

.modal__tick{
  display:grid;place-items:center;width:52px;height:52px;margin-bottom:18px;
  border-radius:50%;background:var(--green-soft);color:var(--green);
}
.modal__tick svg{width:26px;height:26px}

@media (max-width:560px){
  .modal__card{padding:28px 22px 26px;border-radius:var(--r-lg)}
  .fields{grid-template-columns:1fr}
  .modal__actions .btn{width:100%}
}


/* -------------------------------------------------------------- launcher -- */
/* The floating chat button and its panel. Both are created hidden and only
   revealed by main.js — with no JavaScript there is nothing to open, and the FAQ
   section carries the whole content anyway. */
.launch{
  position:fixed;right:22px;bottom:22px;z-index:90;
  width:60px;height:60px;border-radius:50%;cursor:pointer;padding:0;
  /* A ring rather than a flat edge, so a photographed face still reads as a
     control and not as a stray image sitting on the page. */
  border:2.5px solid #fff;background:var(--red);color:#fff;
  display:grid;place-items:center;
  box-shadow:0 12px 30px rgba(13,24,34,.28), 0 2px 6px rgba(13,24,34,.18);
  transition:transform .24s var(--ease),opacity .3s var(--ease),box-shadow .24s var(--ease);
}
.launch:hover{box-shadow:0 16px 36px rgba(13,24,34,.34), 0 2px 6px rgba(13,24,34,.2)}
/* The face fills the button; closing reveals the red beneath it with the cross. */
.launch__ico img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
.launch:hover{transform:translateY(-3px) scale(1.04)}
.launch:focus-visible{outline:3px solid #fff;outline-offset:3px}
.launch svg{fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
/* Both marks live in the same cell and cross-fade, so the button never resizes. */
.launch__ico,.launch__x{grid-area:1/1;width:100%;height:100%;display:grid;place-items:center;
  transition:opacity .2s var(--ease),transform .24s var(--ease)}
.launch__x{opacity:0;transform:rotate(-90deg)}
.launch[aria-expanded="true"] .launch__ico{opacity:0;transform:rotate(90deg)}
.launch[aria-expanded="true"] .launch__x{opacity:1;transform:none}
.launch__dot{
  position:absolute;top:1px;right:1px;width:14px;height:14px;border-radius:50%;
  background:#3DD68C;border:2.5px solid #fff;pointer-events:none;z-index:91;
  transition:opacity .2s var(--ease);
}
.launch[aria-expanded="true"] .launch__dot{opacity:0}
/* Held back until the hero has been passed, so it never covers the first CTA. */
.launch.is-hidden{opacity:0;pointer-events:none;transform:translateY(12px) scale(.9)}

.dock{
  position:fixed;right:22px;bottom:92px;z-index:89;
  width:min(374px, calc(100vw - 44px));
  display:flex;flex-direction:column;overflow:hidden;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-xl);
  box-shadow:0 30px 70px rgba(13,24,34,.26), 0 4px 12px rgba(13,24,34,.10);
  transform-origin:bottom right;
}
.dock[hidden]{display:none}
.dock.is-in{animation:dockIn .26s var(--ease) both}
@keyframes dockIn{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
.dock .chat__thread{max-height:min(48vh,340px);padding:18px 16px}
.dock .chat__asks{padding:13px 16px;max-height:132px;overflow-y:auto}
.dock .ask{font-size:.81rem;padding:8px 13px}
.dock .chat__foot{padding:0 16px 14px;font-size:.8rem}
.dock .msg{max-width:96%}

@media (max-width:560px){
  .launch{right:16px;bottom:16px;width:52px;height:52px}
  .dock{right:12px;left:12px;bottom:78px;width:auto}
}

/* ----------------------------------------------------------- animation -- */
.reveal{opacity:0;transform:translateY(20px)}
.reveal.is-in{opacity:1;transform:none;transition:opacity .7s var(--ease),transform .7s var(--ease)}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
  .reveal{opacity:1;transform:none}

  /* The blanket duration override is wrong for an infinite loop — it would restart the
     marquee thousands of times a second, which is a strobe, not a stilled animation.
     It is stopped outright and becomes a row that can be scrolled by hand instead. The
     second copy exists only to hide the loop's seam, so it goes with the motion. */
  .ticker__track{animation:none!important;transform:none!important}
  .ticker__track[aria-hidden]{display:none}
  .ticker{overflow-x:auto;-webkit-mask-image:none;mask-image:none}
}

/* ---------------------------------------------------------- responsive -- */
@media (max-width:1080px){
  .hero__in{grid-template-columns:1fr;gap:44px}
  .lede{max-width:none}
  .foot__in{grid-template-columns:repeat(2,1fr);gap:32px}
  .foot__brand{grid-column:1/-1}
}

@media (max-width:900px){
  .nav__links,.nav__cta{display:none}
  .burger{display:grid;margin-left:auto}
  .nav.is-open .drawer{display:flex}
}

@media (max-width:560px){
  body{font-size:16px}
  .wrap{padding-inline:20px}
  /* Smaller type and a shorter loop, so the band still reads as a run of claims on a
     phone rather than one very long sentence going past. */
  .ticker__track li{font-size:.94rem;padding:18px 0}
  .ticker__track li::after{margin:0 22px}
  .ticker__track{animation-duration:34s}
  .foot__in{grid-template-columns:1fr}
  .btn--lg{width:100%}
  .hero__actions,.cta__actions{flex-direction:column;align-items:stretch}
}

/* ------------------------------------------------------------- the sale, moving --
   An animated strip under the film. The fan beside the film says where the seven
   writes land; this says they travel together and arrive at once — which is the
   part of the claim that is about time, and the part a still picture cannot carry.

   SVG from the sprite rather than a GIF: sharp at any size, no extra request, and
   it recolours with the section instead of baking a background into a bitmap. */
.flow{
  position:relative;margin:0 0 26px;padding:20px 22px;
  background:var(--deep-2);border:1px solid var(--deep-line);border-radius:var(--r-lg);
  overflow:hidden;
}

.flow__line{
  list-style:none;margin:0;padding:0;position:relative;
  display:flex;align-items:center;justify-content:space-between;gap:8px;
}

/* The rail sits behind the icons, inset by half an icon at each end so it runs
   between them rather than out past the first and last. */
.flow__line::before{
  content:"";position:absolute;left:20px;right:20px;top:20px;height:2px;border-radius:2px;
  background:linear-gradient(90deg,rgba(251,44,35,.42),rgba(124,147,168,.34),rgba(0,145,58,.42));
}

/* The pulse: one pass of light along the rail, timed to arrive at each icon as that
   icon lights. background-position on a wide gradient rather than a moving element,
   so it cannot be knocked out of line by the flex gaps. */
.flow__line::after{
  content:"";position:absolute;left:20px;right:20px;top:20px;height:2px;border-radius:2px;
  background:linear-gradient(90deg,transparent 0%,transparent 38%,rgba(255,255,255,.95) 46%,
             rgba(255,255,255,.95) 50%,transparent 58%,transparent 100%);
  background-size:260% 100%;
  animation:flowPulse 4.4s linear infinite;
}
@keyframes flowPulse{
  0%   {background-position:120% 0}
  62%  {background-position:-60% 0}
  100% {background-position:-60% 0}   /* holds off-rail while COMMIT lands */
}

.flow__line li{
  position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:7px;
  font:600 .68rem/1 var(--mono);letter-spacing:.06em;text-transform:uppercase;
  color:var(--deep-mute);
  animation:flowNode 4.4s var(--ease) infinite;
  animation-delay:calc(var(--i) * .58s);
}

.flow__ico{
  display:grid;place-items:center;width:40px;height:40px;border-radius:12px;
  background:var(--deep-2);border:1.5px solid var(--deep-line);color:var(--deep-mute);
}
.flow__ico svg{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;display:block}

/* Lit only in passing. The node is dim before and after, so the eye follows one
   moving thing rather than reading six things that all glow. */
@keyframes flowNode{
  0%,4%   {color:var(--deep-mute)}
  9%      {color:#fff}
  20%     {color:#fff}
  32%,100%{color:var(--deep-mute)}
}
.flow__line li{--lit:0}
@keyframes flowIco{
  0%,4%   {border-color:var(--deep-line);background:var(--deep-2);transform:none;box-shadow:none}
  9%      {border-color:var(--red-hi);background:rgba(251,44,35,.14);transform:translateY(-3px);
           box-shadow:0 8px 20px rgba(251,44,35,.22)}
  20%     {border-color:var(--red-hi);background:rgba(251,44,35,.14);transform:translateY(-3px)}
  32%,100%{border-color:var(--deep-line);background:var(--deep-2);transform:none;box-shadow:none}
}
.flow__line li .flow__ico{
  animation:flowIco 4.4s var(--ease) infinite;
  animation-delay:calc(var(--i) * .58s);
}

.flow__chip{
  display:inline-block;padding:11px 15px;border-radius:12px;
  font:700 .72rem/1 var(--mono);letter-spacing:.12em;
  color:var(--deep-mute);background:var(--deep-2);border:1.5px solid var(--deep-line);
  animation:flowCommit 4.4s var(--ease) infinite;
  animation-delay:2.6s;
}
/* Green, and held longer than the nodes — it is the resolution, not another step. */
@keyframes flowCommit{
  0%,6%   {color:var(--deep-mute);border-color:var(--deep-line);background:var(--deep-2);box-shadow:none}
  12%     {color:#7BE8A6;border-color:rgba(123,232,166,.6);background:rgba(0,145,58,.18);
           box-shadow:0 8px 24px rgba(0,145,58,.28)}
  40%     {color:#7BE8A6;border-color:rgba(123,232,166,.6);background:rgba(0,145,58,.18)}
  55%,100%{color:var(--deep-mute);border-color:var(--deep-line);background:var(--deep-2);box-shadow:none}
}
.flow__end b{display:none}

/* Motion is the whole content here, so with it turned off the strip is shown in its
   arrived state — everything lit and committed — rather than left mid-cycle. */
@media (prefers-reduced-motion:reduce){
  .flow__line::after,.flow__line li,.flow__line li .flow__ico,.flow__chip{animation:none}
  .flow__line li{color:#fff}
  .flow__line li .flow__ico{border-color:var(--red-hi);background:rgba(251,44,35,.12)}
  .flow__chip{color:#7BE8A6;border-color:rgba(123,232,166,.6);background:rgba(0,145,58,.18)}
}

@media (max-width:620px){
  .flow{padding:16px 12px}
  .flow__line{gap:4px}
  .flow__line li{font-size:.58rem;letter-spacing:.03em}
  .flow__ico{width:32px;height:32px;border-radius:10px}
  .flow__ico svg{width:16px;height:16px}
  .flow__line::before,.flow__line::after{left:16px;right:16px;top:16px}
  .flow__chip{padding:9px 9px;font-size:.6rem;letter-spacing:.06em}
}

/* ------------------------------------------------------------------- add-ons --
   Three cards, deliberately not styled as a fourth plan: the plans are a choice of
   one, these are a set you can take any of. Lighter surface, no flag, no CTA per
   card — one link under the row instead, so nothing competes with the plan CTAs
   further up the page. */
.addons{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;align-items:stretch;margin-top:34px}

.addon{
  display:flex;flex-direction:column;
  background:var(--canvas);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:24px 22px;box-shadow:var(--sh-1);
}
.addon h3{font-size:1.12rem;margin:8px 0 0}

/* One-time versus monthly is the thing a buyer needs first here — a migration priced
   per month would be read as a subscription, so the term leads. */
.addon__tag{
  align-self:flex-start;padding:5px 10px;border-radius:99px;
  font:700 .66rem/1 var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:var(--red);background:var(--red-soft);border:1px solid rgba(224,30,20,.2);
}
.addon__body{font-size:.88rem;line-height:1.65;color:var(--muted);margin-top:10px}

.addon__pts{list-style:none;margin:14px 0 0;padding:0;display:flex;flex-direction:column;gap:9px}
.addon__pts li{position:relative;padding-left:20px;font-size:.83rem;line-height:1.55;color:var(--ink-2)}
.addon__pts li::before{
  content:"";position:absolute;left:0;top:.5em;width:7px;height:7px;border-radius:50%;
  background:var(--green-soft);border:1.5px solid var(--green);
}

/* margin-top:auto pins the price to the bottom edge, so three cards of unequal prose
   still line their prices up with each other. */
.addon__price{margin-top:auto;padding-top:18px}
.addon__amt{font:800 1.5rem/1 var(--display);color:var(--ink);letter-spacing:-.02em}
.addon__note{
  font-size:.78rem;line-height:1.5;color:var(--muted);margin-top:7px;
  /* Two lines' worth for every card. One note wraps and the others do not, and
     without this the price above it rides up and the three stop lining up. */
  min-height:3em;
}

.addons__foot{margin-top:22px;font-size:.88rem;color:var(--muted)}
.addons__foot a{color:var(--red);font-weight:700}

@media (max-width:900px){ .addons{grid-template-columns:1fr;gap:14px} }

/* --------------------------------------------------------------------- about --
   Reuses .sec/.sechead/.wrap wholesale; only the three card shapes on this page
   are new. Nothing here introduces a colour or a radius the rest of the site does
   not already use. */
.abt__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:32px;align-items:stretch}
.abt__grid--two{grid-template-columns:repeat(2,1fr)}

.abt{
  display:flex;flex-direction:column;
  background:var(--canvas);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:24px 22px;box-shadow:var(--sh-1);
}
.abt--flat{box-shadow:none;background:var(--canvas)}
.abt h3{font-size:1.1rem;margin:0}
.abt p{font-size:.88rem;line-height:1.65;color:var(--muted);margin-top:8px}

.abt__ico{
  display:grid;place-items:center;width:42px;height:42px;margin-bottom:14px;
  border-radius:12px;background:var(--red-soft);color:var(--red);
}
.abt__ico svg{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

.abt__where{
  font:700 .68rem/1 var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin-top:6px;
}
/* auto keeps the three links on one line across cards of unequal prose. */
/* padding-top carries the gap; padding-bottom exists only to bring the touch area
   to 44px on a phone. It sat at 39 — near enough to look fine and far enough to
   be missed by a thumb. */
.abt__link{margin-top:auto;padding-top:16px;padding-bottom:6px;font-size:.86rem;font-weight:700;color:var(--red)}
.abt__link:hover{text-decoration:underline;text-underline-offset:3px}

/* A description list, because that is what this is — the label is the term and the
   detail is its definition, which a screen reader then reads as a pair. */
.abt__facts{
  display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin:32px 0 0;
}
.abt__facts > div{
  padding:18px 20px;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--soft);
}
.abt__facts dt{
  font:700 .66rem/1 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
}
.abt__facts dd{margin:9px 0 0;font-size:.94rem;line-height:1.6;color:var(--ink);font-weight:600}
.abt__facts a{color:var(--red);font-weight:700}
.abt__facts a:hover{text-decoration:underline;text-underline-offset:3px}

.abt__legalnote{margin-top:22px;font-size:.86rem;line-height:1.7;color:var(--muted)}
.abt__legalnote a{color:var(--red);font-weight:700}

@media (max-width:900px){
  .abt__grid,.abt__grid--two,.abt__facts{grid-template-columns:1fr;gap:14px}
}

/* ------------------------------------------------- footer: apps coming soon --
   Sits at the foot of the rightmost column, so it lands in the bottom-right of the
   footer without competing with the copyright line beneath it. Not links: nothing
   is downloadable yet, and a dead store badge is worse than a plain sentence. */
.foot__apps{margin-top:18px;padding-top:16px;border-top:1px solid var(--deep-line)}
.foot__apps-h{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  font-size:.82rem;font-weight:700;color:var(--deep-ink);
}
.foot__soon{
  padding:3px 8px;border-radius:99px;
  font:700 .6rem/1 var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:#FFD9A0;background:rgba(255,217,160,.12);border:1px solid rgba(255,217,160,.32);
}
.foot__stores{list-style:none;margin:11px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:9px}
/* The badges are finished artwork — no pill, no border, nothing of ours drawn around
   them. Both are set to one height and left to take their own widths, which is how
   the two stores' own guidelines say to place them side by side. */
.foot__stores img{display:block;height:38px;width:auto;opacity:.92}

/* --------------------------------------------- touch targets on small screens --
   Footer links were 24px tall and the social marks 38px, both under the 44px a
   thumb needs. The padding is added on the phone breakpoint only — on a pointer
   device 24px is a comfortable target and the extra height would just stretch the
   footer. Negative margins keep the visible rhythm identical: the row grows into
   the gap that was already between the links rather than pushing them apart. */
@media (max-width:640px){
  .foot__col a,
  .foot__col--contact a{
    padding-block:10px;margin-block:-10px;   /* 24 + 20 = 44px of target */
  }
  .foot__col{gap:20px}                        /* was 10 — restores the visual gap */
  .foot__social a{width:44px;height:44px}     /* was 38 */
  .prod__cta{padding-block:10px;margin-block:-10px}
}

/* ---------------------------------------------- pricing, on a 320px handset --
   Two things pushed past the viewport on the narrowest phones still in use.

   The term switcher is one nowrap pill containing two nowrap buttons, so at 320
   it could only overflow. It wraps to two rows there and the pill becomes a
   rounded rectangle rather than a lozenge, which is the only shape that fits.

   The module table is 560px wide by design — fourteen modules against four plans
   does not compress — so its container scrolls it rather than the page. Without
   this, the whole document scrolled sideways to accommodate one table. */
@media (max-width:360px){
  .term{display:flex;flex-wrap:wrap;justify-content:center;border-radius:var(--r-lg);max-width:100%}
  .term__btn{flex:1 1 auto;padding:11px 14px;font-size:.84rem;white-space:normal}
  .term__save{display:block;margin-top:2px}
}
.mods{overflow-x:auto;-webkit-overflow-scrolling:touch}
