/*
 * CompoundOS — marketing site
 * ─────────────────────────────────────────────────────────────────────────────
 * Brand direction: "Registry". CompoundOS is the official record of who came
 * through the gate, so the look borrows from records: clean paper, black ink,
 * and the violet-blue of an official rubber stamp.
 *
 * System rules (founder's reviews + taste-skill + Vercel guidelines):
 *  - Solid colours from the tokens below ONLY. No gradients, blur, textures,
 *    transparency or soft shadows. Separation comes from 1px borders.
 *  - One page theme (light). Sections only alternate paper / sheet.
 *  - Violet = brand, actions and "verified". Green / red = gate results only.
 *  - Shapes: controls (buttons, inputs, language switch) 10px; cards 16px;
 *    status chips fully round.
 *  - Every desktop section is one screen under the sticky header; its content
 *    is centred and fits a 1280×600 window. Sizes follow the window height.
 *  - Motion only on opacity/transform/scale, always off under reduced motion.
 *
 * Contrast figures are WCAG ratios computed from the hex values. Logical
 * properties (inline-start/end) everywhere, so Arabic (RTL) and English (LTR)
 * share one stylesheet.
 */

:root {
  /* Surfaces */
  --paper: #F7F7F4;        /* page, alternate sections */
  --sheet: #FFFFFF;        /* cards, alternate sections */
  --line: #DEDFDA;         /* dividers inside cards */
  --line-strong: #C5C7C0;  /* card and control outlines */

  /* Text */
  --ink: #12161C;          /* 16.9:1 on paper */
  --ink-2: #4E5560;        /*  7.0:1 on paper — secondary text */
  --ink-3: #686E78;        /*  4.8:1 on paper — meta text, 12px and up */

  /* Brand */
  --stamp: #3B34A6;        /*  8.8:1 on paper · white on stamp 9.4:1 */
  --stamp-deep: #2B2585;   /* hover / pressed */
  --stamp-wash: #ECEBF8;   /* stamp on it 8.0:1 */

  /* Gate results */
  --granted: #17803D;      /* fills: white on it 5.0:1 */
  --granted-ink: #136B33;  /* text on granted-wash 5.7:1 */
  --granted-wash: #E3F1E7;
  --refused: #C2261D;      /* text on refused-wash 5.0:1 */
  --refused-wash: #FBE8E6;
  --void: #5D636D;         /* neutral status, 5.2:1 on void-wash */
  --void-wash: #ECEDEF;

  /* Type */
  --font-display: "Alexandria", "IBM Plex Sans Arabic", system-ui, sans-serif;
  --font-body: "IBM Plex Sans", "IBM Plex Sans Arabic", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Shape */
  --r-ctl: 10px;
  --r-card: 16px;

  /* Layout */
  --wrap: 1240px;
  --gutter: clamp(16px, 4vw, 32px);
  --header-h: 4.25rem;
  --section-pad: clamp(1.5rem, 4.5svh, 3rem);
  --ease: cubic-bezier(.2, .8, .2, 1);

  color-scheme: light;
}

/* More contrast on request: secondary text 10.9:1, meta text 8.1:1. */
@media (prefers-contrast: more) {
  :root {
    --ink-2: #333941;
    --ink-3: #464C55;
    --line: #A7A9A2;
    --line-strong: #6E7169;
  }
}

/* ── Base ─────────────────────────────────────────────────────────────────── */

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

html {
  overflow-x: clip;
  /* A slim scrollbar in the page's colours (meta-text grey, 4.8:1 on paper). */
  scrollbar-width: thin;
  scrollbar-color: var(--ink-3) var(--paper);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 1px);
  -webkit-tap-highlight-color: transparent;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; interpolate-size: allow-keywords; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1.0625rem/1.65 var(--font-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
html[lang="ar"] body { line-height: 1.8; }

h1, h2, h3, p, ol, ul, dl, dd, figure { margin: 0; }
ol, ul { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; touch-action: manipulation; }
a, summary { touch-action: manipulation; }

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

.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;
}

.skip {
  position: absolute;
  inset-inline-start: 1rem;
  top: -5rem;
  z-index: 100;
  padding: .7rem 1rem;
  border-radius: var(--r-ctl);
  background: var(--ink);
  color: var(--snow);
  font-weight: 600;
  text-decoration: none;
}
.skip:focus { top: 1rem; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* One icon family everywhere: Phosphor Regular (filled paths, 256 grid). */
.icon { flex: none; fill: currentColor; }
.icon { width: 1.25rem; height: 1.25rem; }

/* One icon tile everywhere (tailored points, security tiles). */
.icon-tile {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.5rem; height: 2.5rem;
  border-radius: var(--r-ctl);
  background: var(--stamp-wash);
  color: var(--stamp);
}

/* Overlay scrollbar (main.js, mouse and trackpad only; touch keeps its own).
   The browser's bar is hidden so the page runs edge to edge; a slim thumb
   floats over it while scrolling or near the edge, and works like the real
   one: drag it, or click the track to move a page. */
html.has-oscroll { scrollbar-width: none; }
html.has-oscroll::-webkit-scrollbar { display: none; }
.oscroll {
  position: fixed;
  inset-block: 0;
  inset-inline-end: 0;
  z-index: 30;
  width: 16px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s linear;
}
.oscroll.is-on { opacity: 1; pointer-events: auto; }
.oscroll[hidden] { display: none; }
.oscroll-thumb {
  position: absolute;
  top: 0;
  inset-inline-end: 4px;
  width: 6px;
  border-radius: 999px;
  background: var(--ink-3);
  touch-action: none;
  transition: width .15s linear, background-color .15s linear;
  will-change: transform; /* moves every frame: its own layer, so the page is never repainted for it */
}
.oscroll:hover .oscroll-thumb,
.oscroll.is-drag .oscroll-thumb { width: 9px; background: var(--stamp); }
@media (prefers-reduced-motion: reduce) {
  .oscroll, .oscroll-thumb { transition: none; }
}
@media print { .oscroll { display: none; } }

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

.eyebrow {
  margin-block-end: .9rem;
  color: var(--stamp);
  font: 600 .9375rem/1.4 var(--font-body);
}

.display {
  font-family: var(--font-display);
  font-weight: 650;
  font-size: clamp(2.25rem, min(4vw, 7.4svh), 3.25rem);
  line-height: 1.08;
  letter-spacing: -.03em;
  text-wrap: balance;
}
html[lang="ar"] .display { line-height: 1.32; letter-spacing: 0; }

.lede {
  max-width: 30em;
  color: var(--ink-2);
  font-size: clamp(1.0625rem, 1rem + .3vw, 1.25rem);
  text-wrap: pretty;
}

.head {
  max-width: 52rem;
  margin-inline: auto;
  margin-block-end: clamp(1.25rem, 3.5svh, 2.25rem);
  text-align: center;
}
.title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.75rem, min(1.15rem + 1.7vw, 6.2svh), 2.5rem);
  line-height: 1.2;
  letter-spacing: -.02em;
  text-wrap: balance;
}
html[lang="ar"] .title { line-height: 1.45; letter-spacing: 0; }
.sub {
  margin-block-start: .5rem;
  color: var(--ink-2);
  font-size: clamp(1.0625rem, 1rem + .3vw, 1.1875rem);
  text-wrap: pretty;
}

h3 { font-family: var(--font-body); font-weight: 600; font-size: 1.0625rem; line-height: 1.45; }

/* ── Buttons and controls (10px) ──────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  min-height: 3rem;
  padding: .7rem 1.35rem;
  border: 0;
  border-radius: var(--r-ctl);
  font: 600 1rem/1.2 var(--font-body);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s ease, box-shadow .15s ease, scale .15s ease;
}
.btn:active { scale: .98; }
.btn-primary { background: var(--stamp); color: var(--snow); }
@media (hover: hover) and (pointer: fine) { .btn-primary:hover { background: var(--stamp-deep); } }
.btn-quiet { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-strong); }
@media (hover: hover) and (pointer: fine) { .btn-quiet:hover { box-shadow: inset 0 0 0 1px var(--ink); } }
.btn-sm { min-height: 2.75rem; padding: .5rem 1rem; font-size: .9375rem; }

/* Language switch: same control shape as the buttons, never underlined. */
.lang {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding-inline: .85rem;
  border-radius: var(--r-ctl);
  background: var(--sheet);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--ink-2);
  font-size: .9375rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition: box-shadow .15s ease, color .15s ease;
}
@media (hover: hover) and (pointer: fine) { .lang:hover { color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); } }
.lang .icon { width: 1.1rem; height: 1.1rem; }
.lang-short { display: none; }
@media (max-width: 640px) {
  .lang { padding-inline: .7rem; }
  .lang .lang-long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lang-short { display: inline; }
}

/* ── Header (solid) ───────────────────────────────────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--paper);
  border-block-end: 1px solid var(--line);
  transition: background-color .2s linear, border-color .2s linear;
}
/* On the hero photo (main.js): no fill, the sky shows through. */
.site-header.is-over { background-color: transparent; border-block-end-color: transparent; }
.header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  min-height: var(--header-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  min-height: 2.75rem;
  color: var(--ink);
  text-decoration: none;
}
.brand-mark { flex: none; width: 28px; height: 28px; color: var(--stamp); }
.brand-word { font: 600 1.25rem/1 var(--font-display); letter-spacing: -.01em; }
.brand-word b { font-weight: 600; color: var(--stamp); }

/* Every nav link behaves the same: hover grows a grey rule, the section you
   are on gets the violet rule (set by main.js). */
.nav { display: none; gap: 1.6rem; margin-inline-start: auto; }
.nav a {
  position: relative;
  padding-block: .6rem;
  color: var(--ink-2);
  font-size: .9375rem;
  font-weight: 500;
  text-decoration: none;
  transition: color .15s ease;
}
.nav a::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: .2rem;
  height: 2px;
  border-radius: 2px;
  background: var(--line-strong);
  scale: 0 1;
  transition: scale .25s var(--ease), background-color .15s ease;
}
@media (hover: hover) and (pointer: fine) { .nav a:hover { color: var(--ink); } .nav a:hover::after { scale: 1 1; } }
.nav a[aria-current="true"] { color: var(--ink); }
.nav a[aria-current="true"]::after { scale: 1 1; background: var(--stamp); }

.header-actions { display: flex; align-items: center; gap: .75rem; margin-inline-start: auto; }

@media (min-width: 1080px) {
  .nav { display: flex; }
  .header-actions { margin-inline-start: 1.25rem; }
}
@media (max-width: 400px) {
  .header-row { gap: .75rem; }
  .brand { gap: .45rem; }
  .brand-mark { width: 24px; height: 24px; }
  .brand-word { font-size: 1.0625rem; }
  .header-actions { gap: .5rem; }
  .btn-sm { padding-inline: .8rem; }
}

/* ── Sections: one screen each on desktop ─────────────────────────────────── */

.section {
  padding-block: 4rem;
  border-block-start: 1px solid var(--line);
}
.how, .tailored, .faq { background: var(--sheet); }
.board, .security, .cta { background: var(--paper); }

@media (min-width: 900px) and (min-height: 560px) {
  .screen {
    display: grid;
    align-content: center;
    min-height: calc(100svh - var(--header-h) - 1px);
    padding-block: var(--section-pad);
  }
}

/* Scroll reveal (main.js adds .is-in). Without JS everything is simply shown. */
.js [data-reveal] {
  opacity: 0;
  translate: 0 18px;
  transition: opacity .7s var(--ease), translate .7s var(--ease);
  transition-delay: calc(var(--i, 0) * 80ms);
}
.js [data-reveal].is-in { opacity: 1; translate: 0 0; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; translate: none; transition: none; }
}
@media print {
  .js [data-reveal] { opacity: 1; translate: none; }
}

/* Section titles rise line by line from behind their own lower edge
   (main.js splits them into .line > .line-in and adds .is-risen). The padding
   keeps Arabic dots and descenders inside each line's mask. Titles rise
   instead of fading, so their own fade is off. */
.js .title[data-reveal] { opacity: 1; translate: none; transition: none; }
.title.is-split .line {
  display: block;
  overflow: hidden;
  padding-block: .12em .16em;
  margin-block: -.12em -.16em;
}
.title.is-split .line-in {
  display: block;
  transform: translateY(110%);
  transition: transform .9s var(--ease);
  transition-delay: calc(var(--l, 0) * 90ms);
}
.title.is-split.is-risen .line-in { transform: none; }
@media print {
  .title.is-split .line-in { transform: none; }
}

/* ── Hero: a day at the gate ─────────────────────────────────────────────────
   The photo is the first screen; the header (transparent over it) and the
   promise sit on its sky. With JS and motion allowed, the stage is held while
   the reader scrolls a short run (main.js):
     · the barrier rises (one arm cut from the photo, rotated over it,
       tools/day-scene.py) and the promise lifts away,
     · the same gate lives one day: 07:10, 21:00, 02:40. The photos
       cross-fade and one solid card rolls to each hour,
     · at night the card and the header turn dark with the light.
   Then "How it works" slides up over the held stage as a sheet, arriving in
   layers. Without JS, under reduced motion and in print: the morning gate,
   then the day as a row of cards, on paper. The Arabic page mirrors the
   photo so its sky sits on the reading side. */

.hero {
  position: relative;
  margin-block-start: calc(-1 * (var(--header-h) + 1px));
}
.hero-stage {
  position: relative;
  background: var(--paper);
  --card: var(--sheet); --card-line: var(--line-strong); --card-ink: var(--ink);
  --card-ink-2: var(--ink-2); --card-ink-3: var(--ink-3); --card-accent: var(--stamp); --card-tile: var(--stamp-wash);
}
.hero-frame {
  position: relative;
  height: 100svh;
  min-height: 30rem;
  overflow: clip;
  background: var(--line);
}

.hero-photo {
  --fx: .5;
  --fy: 0;
  position: absolute;
  inset: 0;
  container-type: size;
}
[dir="rtl"] .hero-photo { scale: -1 1; }
/* The scene covers the frame like object-fit: cover, anchored at --fx/--fy,
   so the arm can be placed on it in the photo's own proportions. */
.scene {
  --w: max(100cqw, 179.1667cqh);
  --h: max(100cqh, 55.8140cqw);
  position: absolute;
  left: calc((100cqw - var(--w)) * var(--fx));
  top: calc((100cqh - var(--h)) * var(--fy));
  width: var(--w);
  height: var(--h);
}
.hour { position: absolute; inset: 0; will-change: opacity; }
.hour + .hour { opacity: 0; }
.hour img:not(.arm) { display: block; width: 100%; height: 100%; }
/* The night gate out of focus: it fades in behind "How it works" as that
   section arrives (main.js), like a camera refocusing on the new page. */
.scene-blur img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  visibility: hidden;
}
/* The arm, cut from the same photo; its hub is the pivot. */
.arm {
  position: absolute;
  left: 15.625%;
  top: 51.7578%;
  width: 69.5858%;
  max-width: none;
  height: auto;
  transform-origin: 96.0836% 49.3333%;
  transform: rotate(calc(var(--open, 0) * 80deg));
  will-change: transform;
}

.hero-copy {
  position: absolute;
  z-index: 1;
  top: calc(var(--header-h) + clamp(1.25rem, 5svh, 3rem));
  inset-inline-start: max(var(--gutter), 18.5%);
  width: min(42rem, calc(100% - 2 * var(--gutter)));
  opacity: calc(1 - var(--fade, 0));
  translate: 0 calc(var(--fade, 0) * -1.75rem);
}
.hero-copy.is-gone { visibility: hidden; }
.js .hero-copy { will-change: transform, opacity; }
.hero .display { font-size: clamp(2.25rem, min(3.75vw, 8svh), 3.5rem); }
.hero .lede { max-width: none; margin-block-start: .9rem; color: var(--ink); font-weight: 500; }
.cta-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-block-start: 1.5rem; }

/* The day's cards. Their colours follow the light (.hero-stage[data-light], main.js). */
.day {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: 1rem;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 3rem var(--gutter) 1rem;
}
.moment {
  padding: 1.6rem 1.6rem 1.4rem;
  border: 1px solid var(--card-line);
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--card-ink);
}
.moment-when { display: flex; align-items: baseline; gap: .75rem; }
.moment-clock { font: 500 3.25rem/1 var(--font-mono); letter-spacing: -.02em; }
.moment-part { color: var(--card-accent); font: 600 .75rem/1.4 var(--font-body); letter-spacing: .12em; text-transform: uppercase; }
html[lang="ar"] .moment-part { letter-spacing: 0; font-size: .875rem; }
.moment-title { margin-block-start: 1rem; font: 600 1.6rem/1.25 var(--font-display); letter-spacing: -.02em; }
.moment-line { margin-block-start: .4rem; color: var(--card-ink-2); }
.moment-pass {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: .75rem;
  margin-block-start: 1.25rem;
  padding: .8rem;
  border: 1px solid var(--card-line);
  border-radius: 12px;
}
.moment-pass .icon-tile { background: var(--card-tile); color: var(--card-accent); }
.moment-who b { display: block; font-size: .9375rem; font-weight: 600; line-height: 1.4; }
.moment-who small { display: block; color: var(--card-ink-3); font-size: .8125rem; }
.chip--party { background: var(--stamp-wash); color: var(--stamp); }

/* The run (JS + motion allowed): the stage is held for two and a half
   screens of day, then for the slide while "How it works" travels up over it. */
@media (prefers-reduced-motion: no-preference) {
  .js .hero { height: calc(450svh - var(--header-h) - 1px); }
  .js .hero-stage { position: sticky; top: 0; height: 100svh; min-height: 30rem; overflow: clip; }
  .js .hero-frame { position: absolute; inset: 0; height: auto; min-height: 0; }
  /* The day's card is one solid frame (the list itself). It wipes up as the
     gate opens (--shell); inside it, each hour's content takes the place of
     the last, moving up as the next comes in. The frame is never see-through. */
  /* The frame stays put and clips; the card rises into it as the gate opens
     (--shell, main.js), moved by the graphics chip rather than repainted. */
  .js .day-frame {
    position: absolute;
    z-index: 2;
    top: 50%;
    inset-inline-start: max(var(--gutter), 7vw);
    width: min(27.5rem, calc(100% - 2 * var(--gutter)));
    height: var(--shell-h, 20rem);
    margin-block-start: calc(var(--shell-h, 20rem) / -2);
    overflow: hidden;
    border-radius: var(--r-card);
  }
  .js .day {
    display: block;
    max-width: none;
    padding: 0;
    position: absolute;
    inset: 0;
    margin: 0;
    overflow: hidden;
    border: 1px solid var(--card-line);
    border-radius: var(--r-card);
    background: var(--sheet);
    transform: translateY(calc((1 - var(--shell, 0)) * 101%));
    will-change: transform;
  }
  /* Night darkens the card as one layer, following the scroll (--night,
     main.js); the text switches half-way, in the middle of the roll. */
  .js .day::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--ink);
    opacity: var(--night, 0);
    will-change: opacity;
  }
  /* The hours are stacked in the frame and roll up one at a time (--roll,
     main.js), like a departure board: only one hour is ever in view. */
  .js .day > .moment {
    inset: 0 auto auto 0;
    width: 100%;
    border: 0;
    border-radius: 0;
    background: none;
    position: absolute;
    transform: translateY(calc((var(--i, 0) - var(--roll, 0)) * var(--shell-h, 20rem)));
    will-change: transform;
  }

  .js .hero + .section {
    position: relative;
    z-index: 2;
    margin-block-start: calc(-100svh + var(--header-h) + 1px);
    /* A sheet while it travels; as it lands under the header (.is-landed,
       main.js) its corners square off and it is an ordinary section again.
       The corners are filled by two small pieces that fade in, which costs
       nothing to animate, rather than by animating the radius. */
    border-radius: var(--r-card) var(--r-card) 0 0;
  }
  .js .hero + .section::before,
  .js .hero + .section::after {
    content: "";
    position: absolute;
    top: 0;
    width: var(--r-card);
    height: var(--r-card);
    background: inherit;
    opacity: 0;
    transition: opacity .25s linear;
    will-change: opacity;
    pointer-events: none;
  }
  .js .hero + .section::before { left: 0; }
  .js .hero + .section::after { right: 0; }
  .js .hero + .section.is-landed::before,
  .js .hero + .section.is-landed::after { opacity: 1; }
  /* "How it works" arrives in layers: title, each step, the phone last. */
  .how .title { transform: translateY(calc((1 - var(--lay, 1)) * 1.5rem)); }
  .how .steps > li:nth-child(1) { transform: translateY(calc((1 - var(--lay, 1)) * 2.5rem)); }
  .how .steps > li:nth-child(2) { transform: translateY(calc((1 - var(--lay, 1)) * 3.5rem)); }
  .how .steps > li:nth-child(3) { transform: translateY(calc((1 - var(--lay, 1)) * 4.5rem)); }
  .how .shot { transform: translateY(calc((1 - var(--lay, 1)) * 6rem)); }
  /* Everything that moves with the scroll gets its own layer, so a frame only
     moves pictures instead of repainting the screen. */
  .how .title, .how .how-copy > .sub, .how .steps > li, .how .shot { will-change: transform; }
}


/* Phones: the sky is too narrow to write on, so the promise sits on the page
   above the photo, the crop follows the barrier's housing, and the cards sit
   at the photo's foot. */
@media (max-width: 699px) {
  .hero { margin-block-start: 0; }
  .hero-frame { display: flex; flex-direction: column; height: calc(100svh - var(--header-h) - 1px); min-height: 34rem; background: var(--paper); }
  .hero-copy { order: -1; position: relative; top: auto; inset-inline-start: auto; width: auto; padding: 1.75rem var(--gutter) 1.5rem; }
  .hero-photo { --fx: .7; position: relative; flex: 1; }
  /* Phones get their own tall photos (phone-*.webp) and arms, so the scene
     takes the tall proportions and the arm's place in them. */
  .scene { --w: max(100cqw, 55.8140cqh); --h: max(100cqh, 179.1667cqw); }
  .arm { left: -45.5729%; top: 42.4419%; width: 135.7422%; transform-origin: 97.2662% 48.8636%; }
}
@media (max-width: 699px) and (prefers-reduced-motion: no-preference) {
  .js .hero { height: calc(450svh - 2 * (var(--header-h) + 1px)); }
  .js .hero-stage { top: calc(var(--header-h) + 1px); height: calc(100svh - var(--header-h) - 1px); }
  /* During the run the photo fills the stage and the promise sits on its sky,
     lifting away as the gate opens, so the day has the whole screen. */
  .js .hero-frame { display: block; height: auto; min-height: 0; background: var(--line); }
  .js .hero-photo { position: absolute; inset: 0; }
  .js .hero-copy { position: absolute; top: 0; inset-inline: 0; padding: 1.5rem var(--gutter); }
  .js .day-frame { top: auto; bottom: var(--gutter); inset-inline: var(--gutter); width: auto; margin: 0; }
}
@media print {
  .js .hero { height: auto; }
  .js .hero-stage { position: relative; height: auto; }
  .js .hero-frame { position: relative; height: 100svh; }
  .js .day-frame { position: static; height: auto; width: auto; margin: 0; overflow: visible; }
  .js .day { display: grid; position: static; height: auto; max-width: var(--wrap); margin: 0 auto; padding: 3rem var(--gutter) 1rem; overflow: visible; border: 0; background: none; transform: none !important; }
  .js .day::before { display: none; }
  .js .day > .moment { position: static; transform: none !important; border: 1px solid var(--card-line); border-radius: var(--r-card); }
  .hero-copy { opacity: 1 !important; transform: none !important; visibility: visible; }
  .js .hero + .section { margin-block-start: 0; }
}

/* The story's clock on the sections that follow the day. */
.story-time { margin-block-end: .75rem; color: var(--stamp); font: 600 .875rem/1.4 var(--font-body); }
/* The same clock as the day's card in the hero. */
.story-clock { margin-inline-end: .6rem; color: var(--ink); font-size: 1.125rem; font-weight: 500; letter-spacing: -.01em; }
.head .story-time { margin-block-end: .5rem; }

/* Products settle into place as their section scrolls in (Apple-style), run
   by the browser's scroll timeline on the graphics chip, no script. Browsers
   without scroll timelines show them still. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .js .shot--office,
    .js .dshot--monitor,
    .js .tailored .device {
      animation: settle-in linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }
  }
}
@keyframes settle-in {
  from { scale: .9; }
  to { scale: 1; }
}

/* Status chips (gate results). */
.chip {
  display: inline-flex;
  align-items: center;
  padding: .15rem .6rem;
  border-radius: 999px;
  font: 600 .75rem/1.5 var(--font-body);
  white-space: nowrap;
}
.device .chip { padding: .15em .65em; font-size: .75em; }
.chip--granted { background: var(--granted-wash); color: var(--granted-ink); }
.chip--expired { background: var(--refused-wash); color: var(--refused); }
.chip--revoked { background: var(--void-wash); color: var(--void); }

/* ── The phone (real proportions, 9:19.5) ─────────────────────────────────────
   Everything inside is in em, and the phone's font-size follows its height,
   so it is a true scale model at any size. */

.device {
  --ph: 34rem;
  position: relative;
  flex: none;
  height: var(--ph);
  aspect-ratio: 9 / 19.5;
  margin-inline: auto;
  padding: .55em;
  background: var(--ink);
  border-radius: 3.3em;
  font-size: calc(var(--ph) / 40);
  line-height: 1.4;
}
/* Side buttons: volume (left) and power (right), physical sides. */
.device::before, .device::after {
  content: "";
  position: absolute;
  width: .32em;
  border-radius: .2em;
  background: var(--ink);
}
.device::before { left: -.28em; top: 8.5em; height: 3em; box-shadow: 0 4.2em 0 var(--ink); }
.device::after { right: -.28em; top: 11em; height: 5em; }

@media (min-width: 900px) {
  .device { --ph: clamp(380px, calc(100svh - var(--header-h) - 4.5rem), 620px); }
}
@media (max-width: 899px) {
  .device { --ph: min(34rem, 150vw); }
}

.device-screen {
  position: relative;
  display: grid;
  grid-template-rows: 3em minmax(0, 1fr) 2em;
  height: 100%;
  overflow: hidden;
  background: var(--sheet);
  border-radius: 2.8em;
  color: var(--ink);
  text-align: start;
}

.sb {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding-inline: .9em;
  font-size: .92em;
  font-weight: 600;
}
/* Like iOS: time centred in the left ear, icons centred in the right ear. */
.sb-time { justify-self: center; font-variant-numeric: tabular-nums; }
.sb-island { width: 5.4em; height: 1.85em; border-radius: 1em; background: var(--ink); }
/* All three icons share one 11-unit-tall grid and one centre line. */
.sb-icons { display: flex; gap: .28em; align-items: center; justify-self: center; height: 1em; }
.sb-icons svg { flex: none; width: auto; height: .72em; fill: currentColor; }
.sb-icons svg:last-child { height: .76em; }
.sb .dim { color: var(--ink-3); }
.home-bar {
  align-self: center;
  justify-self: center;
  width: 8.5em;
  height: .35em;
  border-radius: 1em;
  background: var(--ink);
}

.panes { position: relative; min-height: 0; }
.pane {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: 3.9em minmax(0, 1fr) 4.6em;
  background: var(--sheet);
}
/* Panes cross-fade as the steps change (state transition). */
.device[data-active] .pane {
  opacity: 0;
  visibility: hidden;
  translate: 0 .8em;
  transition: opacity .45s var(--ease), translate .45s var(--ease), visibility 0s linear .45s;
}
.device[data-active="1"] .pane[data-pane="1"],
.device[data-active="2"] .pane[data-pane="2"],
.device[data-active="3"] .pane[data-pane="3"] {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
  transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
  .device[data-active] .pane { translate: none; transition: none; }
}

.ui-bar {
  display: flex;
  align-items: center;
  gap: .65em;
  padding-inline: 1.1em;
  border-block-end: 1px solid var(--line);
}
.ui-badge {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.4em; height: 2.4em;
  border-radius: .75em;
  background: var(--stamp-wash);
  color: var(--stamp);
}
.ui-badge svg { width: 1.3em; height: 1.3em; }
.ui-badge--solid { background: var(--stamp); color: var(--snow); }
.ui-titles { min-width: 0; }
.ui-titles b { display: block; font-size: 1em; font-weight: 600; line-height: 1.3; white-space: nowrap; }
.ui-titles small { display: block; color: var(--ink-3); font-size: .85em; line-height: 1.3; }

.ui-body {
  display: flex;
  flex-direction: column;
  gap: .9em;
  min-height: 0;
  padding: 1.1em;
}
.ui-body--center { justify-content: center; align-items: center; background: var(--paper); }
.ui-intro {
  display: grid;
  gap: .2em;
  padding: .9em 1em;
  border-radius: .9em;
  background: var(--stamp-wash);
}
.ui-intro b { font: 600 1em/1.35 var(--font-display); text-wrap: balance; }
.ui-intro small { color: var(--ink-2); font-size: .85em; }
.ui-field { display: grid; gap: .35em; }
.ui-label { color: var(--ink-2); font-size: .85em; font-weight: 600; }
.ui-input {
  display: flex;
  align-items: center;
  height: 2.8em;
  padding-inline: .85em;
  border: 1px solid var(--line-strong);
  border-radius: .75em;
  white-space: nowrap;
}
html[dir="rtl"] .ui-input--ltr { justify-content: flex-end; }
.ui-check { display: flex; align-items: center; gap: .6em; font-size: .92em; font-weight: 500; }
.ui-checkbox {
  display: grid;
  place-items: center;
  width: 1.4em; height: 1.4em;
  border-radius: .35em;
  background: var(--stamp);
  color: var(--snow);
}
.ui-checkbox svg { width: .95em; height: .95em; }

.ui-foot {
  display: flex;
  align-items: center;
  gap: .5em;
  padding-inline: 1.1em;
  border-block-start: 1px solid var(--line);
}
.ui-btn {
  display: grid;
  place-items: center;
  flex: 1;
  height: 2.9em;
  border-radius: .75em;
  background: var(--stamp);
  color: var(--snow);
  font-size: .95em;
  font-weight: 600;
  white-space: nowrap;
}
.ui-pill {
  margin-inline: auto;
  padding: .4em 1em;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-2);
  font-size: .85em;
  font-weight: 600;
}

/* Share screen: the pass, then any app. */
.pass {
  display: grid;
  justify-items: center;
  gap: .35em;
  padding: 1em 1.3em 1.1em;
  background: var(--sheet);
  border: 1px solid var(--line);
  border-radius: 1em;
  text-align: center;
}
.pass .qr { width: 8.6em; height: auto; margin-block: .2em; color: var(--ink); }
.pass b { font-size: 1.02em; }
.pass small { color: var(--ink-3); font-size: .82em; }
/* Four equal columns: every app icon centred in its own slot, whatever the label length. */
.ui-foot--apps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); align-items: center; padding-inline: .4em; }
.app { display: grid; justify-items: center; gap: .3em; min-width: 0; color: var(--ink-2); font-size: .78em; font-weight: 500; text-align: center; white-space: nowrap; }
.app-icon {
  display: grid;
  place-items: center;
  width: 2.9em; height: 2.9em;
  border-radius: 50%;
  background: var(--stamp-wash);
  color: var(--stamp);
}
.app-icon svg { width: 1.5em; height: 1.5em; }

/* Gate scan screen. */
.verdict {
  display: flex;
  align-items: center;
  gap: .8em;
  padding: 1em;
  border-radius: .9em;
  background: var(--granted);
  color: var(--snow);
}
.verdict svg { flex: none; width: 2.3em; height: 2.3em; }
.verdict b { display: block; font: 600 1.1em/1.3 var(--font-display); }
.verdict small { display: block; font-size: .82em; }
.ui-dl div {
  display: flex;
  justify-content: space-between;
  gap: .5em;
  padding-block: .6em;
  border-block-end: 1px solid var(--line);
  font-size: .92em;
}
.ui-dl div:last-child { border-block-end: 0; }
.ui-dl dt { color: var(--ink-2); }
.ui-dl dd { margin: 0; font-weight: 600; }

/* Resident home screen (tailored section). */
.ui-hello { font: 600 1.15em/1.3 var(--font-display); }
.ui-body .ui-label + .ui-list { margin-block-start: -.4em; }
.ui-list { border: 1px solid var(--line); border-radius: .75em; }
.ui-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .65em .85em;
  font-size: .95em;
  font-weight: 500;
}
.ui-list li + li { border-block-start: 1px solid var(--line); }

/* ── How it works: steps drive the phone ──────────────────────────────────── */

.how-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.5rem; align-items: center; }
@media (min-width: 900px) {
  .how-grid { grid-template-columns: minmax(0, 34rem) auto; justify-content: center; gap: clamp(3rem, 8vw, 8rem); }
}
.steps { display: grid; gap: .5rem; margin-block: clamp(1rem, 3svh, 1.75rem) 1rem; }
.step {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .1rem 1rem;
  align-items: start;
  width: 100%;
  padding: .9rem 1.15rem;
  overflow: hidden;
  border: 1px solid transparent;
  border-radius: var(--r-card);
  background: transparent;
  text-align: start;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease;
}
@media (hover: hover) and (pointer: fine) { .step:hover { background: var(--paper); } }
.step.is-active { background: var(--paper); border-color: var(--line-strong); }
.step-num {
  display: grid;
  place-items: center;
  width: 2rem; height: 2rem;
  margin-block-start: .1rem;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  color: var(--ink-2);
  font: 600 .9375rem/1 var(--font-display);
  transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
.step.is-active .step-num { background: var(--stamp); border-color: var(--stamp); color: var(--snow); }
.step-text b { display: block; font-size: 1.0625rem; font-weight: 600; line-height: 1.45; }
.step-text span { display: block; color: var(--ink-2); font-size: .9375rem; line-height: 1.5; }

/* The active step carries a solid violet edge on its reading-start side. */
.step::before {
  content: "";
  position: absolute;
  inset-block: .85rem;
  inset-inline-start: 0;
  width: 3px;
  border-radius: 3px;
  background: var(--stamp);
  scale: 1 0;
  transition: scale .25s var(--ease);
}
.step.is-active::before { scale: 1 1; }

/* ── Scenes: one photo per section, our live screen inside it ───────────────
   Each scene is a still of the same gate (tools/scene-shots.py) with a blank
   screen; the page's own screen sits exactly on it through a matrix3d. The
   photo and the screen live on a fixed-size stage (820 × 458 wide, 600 × 800
   tall) that main.js scales to cover the scene, once per resize. Nothing
   in a scene moves with the scroll: its screen changes once, as it lands.
   Without JS the photo shows alone, at its own proportions. */
.shot {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--r-card);
  background: var(--ink);
}
.shot img { display: block; width: 100%; height: auto; }
.shot-ui { display: none; }
.js .shot { aspect-ratio: 820 / 458; }
.js .shot--phone { aspect-ratio: 3 / 4; }
.js .shot-stage { position: absolute; left: 0; top: 0; width: 820px; height: 458px; transform-origin: 0 0; }
.js .shot--phone .shot-stage { width: 600px; height: 800px; }
.js .shot-stage img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; }
.js .shot-ui {
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  overflow: hidden;
  transform-origin: 0 0;
  background: var(--sheet);
  color: var(--ink);
  text-align: start;
}
.shot--phone .shot-ui {
  width: 300px;
  height: 640px;
  border-radius: 40px;
  transform: matrix3d(0.97046,-0.0328427,0,-3.10033e-05,0.021199,0.940444,0,-5.76812e-05,0,0,1,0,137.419,131.613,0,1);
}
.shot--office .shot-ui {
  width: 500px;
  height: 292px;
  transform: matrix3d(1.14786,-0.00543479,0,-1.36054e-05,-0.0176187,1.15239,0,-4.76635e-05,0,0,1,0,120.657,57.4,0,1);
}
.shot--booth .shot-ui {
  width: 252px;
  height: 174px;
  transform: matrix3d(1.70628,-0.00497558,0,-6.49112e-05,-0.0876948,1.70502,0,-0.000200579,0,0,1,0,190.739,76.6522,0,1);
}
@media (max-width: 699px) {
  .js .shot { aspect-ratio: 3 / 4; }
  .js .shot-stage { width: 600px; height: 800px; }
  .shot--booth .shot-ui { transform: matrix3d(1.43869,-0.0173313,0,-6.49112e-05,-0.0647659,1.39409,0,-0.000200579,0,0,1,0,115.5,267,0,1); }
  .shot--office .shot-ui { transform: matrix3d(1.08996,-0.00764928,0,-1.36054e-05,-0.0124747,1.08431,0,-4.76635e-05,0,0,1,0,25.5556,237.778,0,1); }
}

/* The phone at the gate: the founder's real resident and guard screens
   (tools/app-demo, demo data). The steps switch them (main.js §3), and so
   does a tap on the phone. */
.how .shot { width: 100%; max-width: 26rem; margin-inline: auto; }
@media (min-width: 900px) {
  .how .shot { width: min(26rem, calc((100svh - var(--header-h) - 6rem) * .75)); }
}
.shot--phone .pane {
  opacity: 0;
  visibility: hidden;
  transition: opacity .45s var(--ease), visibility 0s linear .45s;
}
.shot--phone[data-active="1"] .pane[data-pane="1"],
.shot--phone[data-active="2"] .pane[data-pane="2"],
.shot--phone[data-active="3"] .pane[data-pane="3"] { opacity: 1; visibility: visible; transition-delay: 0s; }
.ph-tap { position: absolute; inset: 0; border: 0; background: transparent; cursor: pointer; }

/* The management office and the night booth: the real Logs page and the
   real refused scan, as they are. */
.board .shot { width: min(100%, 46rem, calc((100svh - var(--header-h) - 15rem) * 1.79)); margin-inline: auto; }
@media (max-width: 899px) { .board .shot, .board .dshot--monitor { width: min(100%, 30rem); } }
@media (prefers-reduced-motion: reduce) {
  .shot--phone .pane { transition: none; }
}

.caps {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .75rem 2.25rem;
  margin-block-start: clamp(1rem, 2.5svh, 1.5rem);
}
.caps li { display: flex; align-items: center; gap: .5rem; font-size: .9375rem; font-weight: 600; }
.caps .icon { color: var(--ink-2); }

/* ── Designed for your compound ───────────────────────────────────────────── */

.tailor-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.5rem; align-items: center; }
@media (min-width: 900px) {
  .tailor-grid { grid-template-columns: auto minmax(0, 34rem); justify-content: center; gap: clamp(3rem, 8vw, 8rem); }
  .tailor-grid .device { order: -1; }
}
.points {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem 2rem;
  margin-block-start: clamp(1.25rem, 3.5svh, 2rem);
}
@media (min-width: 560px) { .points { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.points li { display: flex; align-items: center; gap: .85rem; font-size: 1.0625rem; font-weight: 600; }

/* ── Security: reassurance, then proof ────────────────────────────────────── */

.secure {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem;
  align-items: stretch;
  max-width: 64rem;
  margin-inline: auto;
}
@media (min-width: 960px) {
  .secure { grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); gap: 1.25rem; }
  /* The scene takes the tiles' height and fills it like a cover photo. */
  .js .security .shot { aspect-ratio: auto; }
}

.tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 1rem; }
@media (max-width: 560px) { .tiles { grid-template-columns: minmax(0, 1fr); } }
.tile {
  padding: 1rem 1.25rem;
  background: var(--sheet);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-card);
  text-align: start;
}
.tile .icon-tile { margin-block-end: .7rem; }
.tile h3 { font-size: 1rem; }
.tile p { margin-block-start: .1rem; color: var(--ink-2); font-size: .9375rem; line-height: 1.55; }

/* ── FAQ ──────────────────────────────────────────────────────────────────── */

.faq-list {
  max-width: 46rem;
  margin-inline: auto;
  border-block-start: 1px solid var(--line);
  text-align: start;
}
.faq-list details { border-block-end: 1px solid var(--line); }
.faq-list summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  padding-block: .95rem;
  font-size: 1.0625rem;
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after {
  content: "+";
  flex: none;
  width: 1.25rem;
  color: var(--ink-2);
  font: 400 1.5rem/1 var(--font-body);
  text-align: center;
  transition: rotate .25s var(--ease);
}
.faq-list details[open] summary::after { rotate: 45deg; }
.faq-list details p { padding-block-end: 1.1rem; color: var(--ink-2); }
/* Smooth open/close where supported (Chrome 131+); instant elsewhere. */
@media (prefers-reduced-motion: no-preference) {
  .faq-list details::details-content {
    block-size: 0;
    overflow: clip;
    transition: block-size .3s var(--ease), content-visibility .3s allow-discrete;
  }
  .faq-list details[open]::details-content { block-size: auto; }
}

/* ── Book a demo (same theme, a card) ─────────────────────────────────────── */

.cta { position: relative; overflow: clip; padding-block: clamp(3.5rem, 9svh, 6rem); }
/* The story's last frame: the gate at night, open, behind the one action. */
.cta-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; }
[dir="rtl"] .cta-photo { scale: -1 1; }
.cta .wrap { position: relative; }
.cta-card {
  max-width: 46rem;
  margin-inline: auto;
  padding: clamp(2rem, 5vw, 3rem);
  background: var(--sheet);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-card);
  text-align: center;
}
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .75rem;
  margin-block-start: 1.75rem;
}
.dev-note {
  margin-block-start: 1.25rem;
  color: var(--ink-3);
  font-size: .8125rem;
}

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

.site-footer { padding-block: 2rem 2.5rem; border-block-start: 1px solid var(--line); }
.footer-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; align-items: center; justify-items: start; }
@media (min-width: 860px) {
  .footer-row { grid-template-columns: auto 1fr auto; gap: 2rem; }
}
.footer-text { display: grid; gap: .15rem; }
.footer-text p { color: var(--ink-2); font-size: .875rem; }
.footer-meta { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; }
.site-footer .brand-word { font-size: 1.125rem; }

/* ══ Sheets (v3, 2026-10-13) ═════════════════════════════════════════════════
   Noir's type and pills, laid out like the best app sites on Awwwards (Reel
   Motion, Wispr Flow): the page is a cool white ground, and every section is
   a rounded sheet set a little in from the window's edges. The sheets take
   turns, light and dark: the gate photo, How it works (light), For
   management (dark), Your compound (light), Security (dark), FAQ (light),
   Book a demo (dark). A dark pill header floats over all of them.
   Headlines in capitals (Geist 500), off-white or near-black pills, hairline
   rows instead of boxes. The product's own screens keep the app's colours;
   violet means "verified" only. Soft shadows only under things you could pick
   up (the phones, the active step). */

:root {
  /* The brand hue drives the product's colour and its tints (OKLCH); the
     page's surfaces and ink use a separate, barely-tinted neutral (--nh). The product colour
     (--brand) is the app's own primary: lightness 0.44, the brand's chroma.
     The brand is "Nile", a deep blue (trust, calm authority), chosen by the
     founder on 2026-10-16 over Oasis (green-teal) and Mulberry (berry). */
  --brand-h: 250;
  --brand-c: .11;
  /* The page itself stays near neutral: its whites and darks carry only a
     trace of a cool hue (never pure white or pure black), so the brand colour
     is the one colour on the page. */
  --nh: 250;
  --brand: oklch(.44 var(--brand-c) var(--brand-h));
  --brand-hover: oklch(.38 var(--brand-c) var(--brand-h));
  --brand-soft: oklch(.94 calc(var(--brand-c) * .35) var(--brand-h));
  --brand-on-dark: oklch(.78 calc(var(--brand-c) * .9) var(--brand-h));
  --night: oklch(.2 0.0048 var(--nh));      /* dark sheets, phone bodies, the hero's card */
  --night-2: oklch(.245 0.0053 var(--nh));
  --snow: oklch(.965 0.0026 var(--nh));     /* text and pills on dark */
  /* The app's own colours, under and over its screens in the device photos. */
  --app-page: #F1F3F4;
  --app-bar: rgb(241 243 244 / .92);
  --app-ink: #12161C;
  --app-island: #050506;
  /* The tap cue on the phone: a light ring with a soft shadow. */
  --tap-fill: oklch(1 0 0 / .35);
  --tap-edge: oklch(1 0 0 / .85);
  --tap-shadow: oklch(0 0 0 / .25);

  --ground: oklch(.935 0.0048 var(--nh));   /* between the sheets */
  --paper: oklch(.985 0.002 var(--nh));    /* light sheet: tinted off-white */
  --sheet: oklch(.995 0.0011 var(--nh));    /* cards on a light sheet */
  --line: oklch(.9 0.004 var(--nh));
  --line-strong: oklch(.82 0.0053 var(--nh));
  --ink: oklch(.22 0.0066 var(--nh));        /* about 15:1 on the sheet */
  --ink-2: oklch(.43 0.0077 var(--nh));     /* about 8:1 */
  --ink-3: oklch(.51 0.007 var(--nh));     /* about 5.6:1 */
  --stamp: var(--brand);                 /* "verified" */
  --stamp-deep: var(--brand-hover);
  --stamp-wash: var(--brand-soft);
  /* Gate results, a little more saturated in the light. */
  --granted: oklch(.52 .155 150); --granted-ink: oklch(.45 .13 150); --granted-wash: oklch(.95 .05 150);
  --refused: oklch(.53 .2 27); --refused-wash: oklch(.95 .035 27);
  --void: oklch(.48 0.0055 var(--nh)); --void-wash: oklch(.93 0.0026 var(--nh));
  /* The one action is the product's colour. */
  --pill: var(--brand);
  --pill-ink: var(--sheet);
  --pill-hover: var(--brand-hover);
  --skeleton: oklch(.92 0.0033 var(--nh));
  --skeleton-hi: oklch(.97 0.0022 var(--nh));

  --font-display: "Geist", "IBM Plex Sans Arabic", system-ui, sans-serif;
  --font-body: "Geist", "IBM Plex Sans Arabic", system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Sheets: how far in from the window, how round. */
  --inset: 8px;
  --r-sheet: 24px;
  --r-card: 20px;
  --header-h: 3.5rem;      /* the floating pill */
  --header-top: calc(var(--inset) + 6px);
  /* Room a sheet keeps at its top for the floating header. */
  --clear: calc(var(--header-h) + 6px + 1.5rem);
  --ease: cubic-bezier(.23, 1, .32, 1);
  color-scheme: light;
}
@media (min-width: 700px) {
  :root { --inset: 12px; --r-sheet: 32px; --r-card: 26px; }
}
/* Dark sheets (and the hero's card). */
.board, .security, .cta, .hero-stage {
  --paper: var(--night);
  --sheet: var(--night-2);
  --line: oklch(.3 0.0044 var(--nh));
  --line-strong: oklch(.38 0.0048 var(--nh));
  --ink: var(--snow);                    /* about 15:1 on the dark sheet */
  --ink-2: oklch(.76 0.0044 var(--nh));      /* about 8:1 */
  --ink-3: oklch(.66 0.0044 var(--nh));      /* about 5.6:1 */
  --stamp: var(--brand-on-dark);
  --stamp-wash: oklch(.28 calc(var(--brand-c) * .5) var(--brand-h));
  --granted-ink: oklch(.82 .12 150); --granted-wash: oklch(.27 .05 150);
  --refused: oklch(.75 .14 27); --refused-wash: oklch(.27 .05 27);
  --void: oklch(.76 0.0044 var(--nh)); --void-wash: oklch(.27 0.0033 var(--nh));
  --pill: var(--snow);
  --pill-ink: var(--night);
  --pill-hover: oklch(.99 0.0013 var(--nh));
  --skeleton: oklch(.27 0.0044 var(--nh));
  --skeleton-hi: oklch(.33 0.0048 var(--nh));
  color-scheme: dark;
}
/* The app's own colours, wherever its screens appear. */
.shot-ui {
  --paper: #F7F7F4; --sheet: #FFFFFF; --line: #DEDFDA; --line-strong: #C5C7C0;
  --ink: #12161C; --ink-2: #4E5560; --ink-3: #686E78;
  color-scheme: light;
}

html { scroll-padding-top: var(--inset); scrollbar-color: var(--ink-3) var(--ground); }
body { background: var(--ground); color: var(--ink); font-size: 1rem; line-height: 1.6; }
::selection { background: var(--ink); color: var(--paper); }
:focus-visible { outline-color: currentColor; }
.skip { z-index: 40; background: var(--pill); color: var(--pill-ink); border-radius: 999px; }
.oscroll:hover .oscroll-thumb,
.oscroll.is-drag .oscroll-thumb { background: var(--ink); }

/* Type: one family; headlines in capitals, tight, medium weight. */
.display, .title {
  font-family: var(--font-display);
  font-weight: 500;
  text-transform: uppercase;
  line-height: 1;
  letter-spacing: -.012em;
}
.display, .hero .display { font-size: clamp(2.5rem, min(5.2vw, 10.5svh), 4.5rem); }
.title { font-size: clamp(2rem, min(3.9vw, 8.5svh), 3.5rem); }
html[lang="ar"] .display, html[lang="ar"] .title { text-transform: none; font-weight: 600; line-height: 1.3; letter-spacing: 0; }
html[lang="ar"] .hero .display { font-size: clamp(2.25rem, min(4.4vw, 8.6svh), 3.75rem); }
.lede, .sub { color: var(--ink-2); }
.sub { max-width: 40em; margin-inline: auto; margin-block-start: .9rem; font-size: clamp(1rem, .95rem + .25vw, 1.125rem); line-height: 1.5; text-wrap: pretty; }
.head .sub { text-wrap: balance; }
h3 { font-weight: 500; }
.story-time { display: none; }

/* Pills. */
.btn { border-radius: 999px; min-height: 3rem; padding: .8rem 1.75rem; font-weight: 500; transition: background-color .15s ease, scale .16s var(--ease); }
.btn:active { scale: .97; }
.btn-primary, .btn-primary:hover { background: var(--pill); color: var(--pill-ink); }
@media (hover: hover) { .btn-primary:hover { background: var(--pill-hover); } }
.btn-quiet { color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-strong); }
.btn-sm { min-height: 2.75rem; padding: .5rem 1.25rem; font-size: .875rem; }
.icon-tile { background: transparent; box-shadow: inset 0 0 0 1px var(--line-strong); color: var(--ink-2); border-radius: 12px; }

/* ── The floating header ─────────────────────────────────────────────────────
   A pill that takes the tone of the sheet under it (main.js §2b):
   see-through at the very top, where it is part of the photo's sky; dark over
   the photo and the dark sheets; light over the light sheets. It sits
   outside the page's flow, so the photo starts at the top of the window. */
.site-header {
  position: fixed;
  top: var(--header-top);
  inset-inline: 0;
  z-index: 20;
  background: none;
  border: 0;
  pointer-events: none;
}
.site-header .header-row {
  --ink: var(--snow); --ink-2: oklch(.8 0.004 var(--nh)); --ink-3: oklch(.66 0.0044 var(--nh)); --line-strong: oklch(1 0 0 / .2);
  --pill: var(--snow); --pill-ink: var(--night); --pill-hover: oklch(.99 0.0013 var(--nh));
  pointer-events: auto;
  flex-wrap: nowrap;
  gap: .75rem;
  width: calc(100% - 2 * var(--inset) - 8px);
  max-width: 76rem;
  min-height: var(--header-h);
  margin-inline: auto;
  padding-inline: 1.25rem .375rem;
  border-radius: 999px;
  background: oklch(.2 0.0048 var(--nh) / .92);
  box-shadow: 0 0 0 1px oklch(1 0 0 / .08), 0 12px 32px -18px oklch(.15 0.0044 var(--nh) / .55);
  color: var(--ink);
  transition: background-color .25s ease, box-shadow .25s ease;
}
.site-header[data-tone="light"] .header-row {
  --ink: oklch(.22 0.0066 var(--nh)); --ink-2: oklch(.43 0.0077 var(--nh)); --ink-3: oklch(.53 0.0066 var(--nh)); --line-strong: oklch(.22 0.0066 var(--nh) / .14);
  --pill: var(--brand); --pill-ink: oklch(.995 0.0011 var(--nh)); --pill-hover: var(--brand-hover);
  background: oklch(.99 0.0015 var(--nh) / .94);
  box-shadow: 0 0 0 1px oklch(.22 0.0066 var(--nh) / .07), 0 12px 32px -18px oklch(.25 .01 var(--nh) / .32);
}
.js .site-header[data-tone="clear"] .header-row {
  background: oklch(.2 0.0048 var(--nh) / 0);
  box-shadow: 0 0 0 1px oklch(1 0 0 / 0), 0 12px 32px -18px oklch(.15 0.0044 var(--nh) / 0);
}
.site-header .brand-mark, .site-header .brand-word, .site-header .brand-word b,
.site-header .nav a, .site-header .lang, .site-header .btn { transition: color .25s ease, background-color .25s ease, box-shadow .25s ease, scale .16s var(--ease); }
.site-header .brand, .site-header .brand-mark, .site-header .brand-word, .site-header .brand-word b { color: var(--ink); }
.brand-mark { width: 24px; height: 24px; }
.brand, .brand-mark, .brand-word b { color: var(--ink); }
.brand-word { font: 600 1.0625rem/1 var(--font-display); letter-spacing: -.01em; }
.brand-word b { font-weight: 400; }
.nav { gap: 1.75rem; }
.site-header .nav a { color: var(--ink-2); font-size: .875rem; }
.site-header .nav a[aria-current="true"] { color: var(--ink); }
@media (hover: hover) and (pointer: fine) { .site-header .nav a:hover { color: var(--ink); } }
.nav a::after { bottom: .3rem; height: 1px; background: var(--ink-3); }
.nav a[aria-current="true"]::after { background: var(--ink); }
.header-actions { gap: .375rem; }
.lang {
  min-height: 2.75rem;
  border-radius: 999px;
  background: transparent;
  box-shadow: none;
  color: var(--ink-2);
  font-size: .875rem;
}
@media (hover: hover) { .lang:hover { color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-strong); } }
@media (min-width: 1080px) { .header-actions { margin-inline-start: 1rem; } }

/* ── Sheets ──────────────────────────────────────────────────────────────── */
.section {
  margin: 0 var(--inset) var(--inset);
  padding-block: calc(var(--inset) + var(--clear)) 3.5rem;
  border: 0;
  border-radius: var(--r-sheet);
  background: var(--paper);
  color: var(--ink);
}
@media (min-width: 900px) and (min-height: 560px) {
  .screen {
    min-height: calc(100svh - 2 * var(--inset));
    padding-block: var(--clear) 2.25rem;
  }
}
.head { margin-block-end: clamp(1.5rem, 4svh, 2.5rem); }

/* Reveal: a little further and softer than before (ease-out, 0.9 s). */
.js [data-reveal] { translate: 0 24px; transition-duration: .9s; }

/* ── Hero: the gate photo as a rounded panel ─────────────────────────────── */
.hero { margin-block-start: 0; }
.hero-stage { background: var(--ground); color: var(--ink); }
.hero-frame {
  height: calc(100svh - 2 * var(--inset));
  margin: var(--inset);
  border-radius: var(--r-sheet);
  background: oklch(.32 0.0026 var(--nh)); /* close to the morning photo, until it has loaded */
}
@media (min-width: 700px) {
  .hero-copy {
    inset-inline: 0;
    width: min(60rem, calc(100% - 2 * var(--gutter)));
    margin-inline: auto;
    top: calc(var(--header-h) + 6px + clamp(1.5rem, 8svh, 4.5rem));
    text-align: center;
  }
  .hero .lede { margin-inline: auto; }
  .cta-row { justify-content: center; }
}
.hero .lede { max-width: 34em; color: var(--snow); font-weight: 400; text-wrap: balance; }
.hero-stage, .hero-stage[data-light="night"] {
  --card: var(--night); --card-line: oklch(.32 0.0044 var(--nh)); --card-ink: var(--snow);
  --card-ink-2: oklch(.76 0.0044 var(--nh)); --card-ink-3: oklch(.66 0.0044 var(--nh)); --card-accent: var(--brand-on-dark); --card-tile: transparent;
}
.moment { border-radius: var(--r-card); }
.moment-title { font-weight: 500; text-transform: uppercase; letter-spacing: -.005em; font-size: 1.4rem; line-height: 1.1; }
html[lang="ar"] .moment-title { text-transform: none; line-height: 1.4; }
.moment-pass { border-radius: 14px; }
.moment-pass .icon-tile { box-shadow: inset 0 0 0 1px var(--card-line); }
.hero-stage[data-light] .chip--granted { background: oklch(.27 .05 150); color: oklch(.82 .12 150); }
.hero-stage[data-light] .chip--expired { background: oklch(.27 .05 27); color: oklch(.76 .14 27); }
.hero-stage[data-light] .chip--party { background: oklch(.28 calc(var(--brand-c) * .5) var(--brand-h)); color: var(--brand-on-dark); }
/* No JS or reduced motion: the day's cards sit on the ground under the photo. */
.day { padding-block: 1rem 2rem; }

@media (prefers-reduced-motion: no-preference) {
  .js .hero { height: 450svh; }
  .js .hero-frame { inset: var(--inset); height: auto; margin: 0; }
  /* The card's two clips (main.js sets where it goes): it slides in as the
     gate opens, and rolls to the next hour as the light passes. */
  .js .day { transition: transform .8s var(--ease); }
  .js .day > .moment { transition: transform .9s cubic-bezier(.65, 0, .35, 1); }
  .js .day-frame {
    inset-inline-start: calc(var(--inset) + max(var(--gutter), 6vw));
    border-radius: var(--r-card);
  }
  .js .day { background: var(--night); border-radius: var(--r-card); }
  .js .day::before { display: none; }
  /* "How it works" slides up over the held photo as a sheet and lands one
     inset from the top, keeping its round corners. */
  .js .hero + .section {
    margin-block-start: calc(-100svh + var(--inset));
    border-radius: var(--r-sheet);
  }
  .js .hero + .section::before,
  .js .hero + .section::after { display: none; }
}

/* ── How it works ────────────────────────────────────────────────────────── */
.how .sub { margin-inline: 0; }
.steps { gap: .375rem; }
.step { padding: .95rem 1.15rem; border-radius: 18px; transition: background-color .2s ease, box-shadow .2s ease; }
.step::before { display: none; }
@media (hover: hover) { .step:hover { background: oklch(.5 0.0088 var(--nh) / .06); } }
.step.is-active {
  background: var(--sheet);
  border-color: transparent;
  box-shadow: 0 0 0 1px oklch(.22 0.0066 var(--nh) / .05), 0 14px 32px -20px oklch(.25 .01 var(--nh) / .45);
}
.step.is-active .step-num { background: var(--brand); border-color: var(--brand); color: var(--sheet); }
.shot { background: var(--night); border-radius: var(--r-card); }
/* The phone's screens: the next one slides in from the reading-end side, as
   in the app; the one leaving fades where it is. */
@media (prefers-reduced-motion: no-preference) {
  .shot--phone .pane {
    transform: translateX(6%);
    transition: opacity .25s ease, transform 0s linear .3s, visibility 0s linear .3s;
  }
  [dir="rtl"] .shot--phone .pane { transform: translateX(-6%); }
  .shot--phone[data-active="1"] .pane[data-pane="1"],
  .shot--phone[data-active="2"] .pane[data-pane="2"],
  .shot--phone[data-active="3"] .pane[data-pane="3"] {
    transform: none;
    transition: opacity .3s var(--ease), transform .5s var(--ease), visibility 0s;
  }
}
/* A press on the phone (main.js §3): a soft ring where the thumb lands. */
.ph-cue {
  position: absolute;
  left: 50%;
  top: 59%;
  z-index: 1;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  border-radius: 50%;
  background: var(--tap-fill);
  box-shadow: 0 0 0 2px var(--tap-edge), 0 6px 18px var(--tap-shadow);
  opacity: 0;
  pointer-events: none;
}
.how .shot { box-shadow: 0 40px 80px -48px oklch(.25 .01 var(--nh) / .55); }
@media (min-width: 900px) {
  .how .shot { width: min(26rem, calc((100svh - 2 * var(--inset) - var(--clear) - 3.5rem) * .75)); }
}

/* ── For management ──────────────────────────────────────────────────────── */
.board .shot { width: min(100%, 44rem, calc((100svh - 2 * var(--inset) - var(--clear) - 19.5rem) * 1.79)); margin-inline: auto; }
.board .dshot--monitor { width: min(100%, 36rem); margin-inline: auto; }
/* Desktop: the words on the reading side, the office monitor beside them as
   large as the window allows, so the record on its screen can be read. */
@media (min-width: 900px) {
  .board .wrap {
    display: grid;
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    grid-template-areas: "head shot" "caps shot";
    align-items: center;
    column-gap: clamp(2.5rem, 5vw, 5rem);
  }
  .board .head { grid-area: head; align-self: end; margin: 0; text-align: start; }
  .board .title { font-size: clamp(2rem, min(3vw, 7svh), 3rem); }
  .board .head .sub { margin-inline: 0; text-wrap: pretty; }
  .board .shot, .board .dshot--monitor {
    grid-area: shot;
    justify-self: end;
    width: min(100%, 52rem, calc((100svh - 2 * var(--inset) - var(--clear) - 4.5rem) * 1.79));
  }
  .board .dshot--monitor {
    width: min(100%, 46rem, calc((100svh - 2 * var(--inset) - var(--clear) - 4.5rem) * 1.356));
    margin: 0;
  }
  .board .caps {
    grid-area: caps;
    align-self: start;
    flex-direction: column;
    align-items: flex-start;
    gap: .7rem;
    margin-block-start: clamp(1.25rem, 3svh, 2rem);
  }
}
.caps .icon { color: var(--ink-3); }
.caps li { font-weight: 500; color: var(--ink-2); }

/* ── Your compound, your app ─────────────────────────────────────────────── */
.trio {
  --ph: clamp(15rem, calc(100svh - 2 * var(--inset) - var(--clear) - 17rem), 30rem);
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: clamp(1rem, 3.5vw, 3rem);
}
.trio-item { display: grid; justify-items: center; gap: 1rem; }
/* The middle phone stands a little forward, like a product shot. */
.trio-item:nth-child(2) { transform: translateY(-1.25rem); }
.handset {
  display: block;
  height: var(--ph);
  aspect-ratio: 600 / 1280;
  padding: calc(var(--ph) * .016);
  border-radius: calc(var(--ph) * .085);
  background: var(--night);
  box-shadow: 0 0 0 1px oklch(.22 0.0066 var(--nh) / .07), 0 40px 70px -40px oklch(.25 .01 var(--nh) / .6);
}
.handset img {
  width: 100%;
  height: 100%;
  border-radius: calc(var(--ph) * .07);
}
.trio-name { display: inline-flex; align-items: center; gap: .55rem; font-size: .9375rem; font-weight: 500; }
.trio-name i { width: .625rem; height: .625rem; border-radius: 50%; background: var(--brand); }
.js .trio-item[data-reveal] { translate: none; transition-duration: 1.1s; }
/* As the section scrolls in, the three phones rise and come forward at
   different speeds (the middle one furthest), the way the office and the
   booth settle in: run by the browser's scroll timeline, no script. */
@media (min-width: 700px) and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .js .trio .handset {
      animation: phone-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 50%;
    }
    .js .trio-item:nth-child(2) .handset { animation-name: phone-rise-mid; }
    .js .dshot--tablet {
      animation: settle-in linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }
  }
}
@keyframes phone-rise { from { scale: .9; translate: 0 64px; } to { scale: 1; translate: 0 0; } }
@keyframes phone-rise-mid { from { scale: .86; translate: 0 112px; } to { scale: 1; translate: 0 0; } }
.pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem;
  margin-block-start: clamp(1.25rem, 3.5svh, 2rem);
}
.pills li {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 2.5rem;
  padding: .4rem 1rem;
  border-radius: 999px;
  background: var(--sheet);
  box-shadow: inset 0 0 0 1px var(--line);
  color: var(--ink-2);
  font-size: .875rem;
  font-weight: 500;
}
.pills .icon { width: 1rem; height: 1rem; color: var(--ink); }
/* Desktop: the words on the reading side, the three phones beside them, as
   tall as the window allows (and narrow enough to fit beside the words). */
@media (min-width: 900px) {
  .tailored .wrap {
    display: grid;
    grid-template-columns: minmax(0, 20rem) auto;
    grid-template-areas: "head trio" "pills trio";
    justify-content: center;
    column-gap: clamp(2.5rem, 5vw, 5rem);
  }
  .tailored .head { grid-area: head; align-self: end; margin: 0; text-align: start; }
  .tailored .head .sub { margin-inline: 0; text-wrap: pretty; }
  .tailored .pills { grid-area: pills; align-self: start; justify-content: flex-start; }
  .trio {
    --ph: clamp(15rem, min(calc(100svh - 2 * var(--inset) - var(--clear) - 6rem), calc(38vw - 6rem)), 30rem);
    grid-area: trio;
    gap: clamp(1rem, 2.5vw, 2rem);
    padding-block-start: 1.25rem; /* room for the middle phone, which stands forward */
  }
}
/* Phones: the three slide sideways, one and a bit on screen. */
@media (max-width: 699px) {
  .trio {
    --ph: min(29rem, 118vw); /* the next phone peeks in half way: there is more to swipe */
    justify-content: flex-start;
    margin-inline: calc(-1 * var(--gutter));
    padding: 1.5rem var(--gutter) .5rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .trio::-webkit-scrollbar { display: none; }
  .trio-item { flex: none; scroll-snap-align: start; }
}

/* ── Security: promises as hairline rows, not boxes ──────────────────────── */
.tiles { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; gap: 0; border-block-start: 1px solid var(--line); }
.tile {
  display: grid;
  grid-template-columns: auto minmax(0, 12rem) minmax(0, 1fr);
  align-items: center;
  gap: 1.25rem;
  padding: .8rem 0;
  border: 0;
  border-block-end: 1px solid var(--line);
  border-radius: 0;
  background: none;
}
.tile .icon-tile { margin: 0; }
.tile h3 { font-size: 1rem; }
.tile p { margin: 0; font-size: .9375rem; }
@media (max-width: 560px) { .tile { grid-template-columns: auto minmax(0, 1fr); row-gap: .15rem; } .tile p { grid-column: 2; } }

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.faq-list summary { font-weight: 500; }
@media (min-width: 900px) {
  /* The question on the left, the answers on the right. */
  .faq .wrap {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 40rem);
    justify-content: center;
    align-items: start;
    gap: clamp(3rem, 8vw, 7rem);
  }
  .faq .head { margin: 0; text-align: start; }
  .faq-list { max-width: none; margin: 0; }
}

/* ── Book a demo: the night gate, one line in capitals, the pill ─────────── */
.cta { overflow: clip; padding-block: clamp(6rem, 18svh, 10rem); }
.cta-card { background: none; border: 0; padding: 0; max-width: 60rem; }
.cta .title { font-size: clamp(2.25rem, min(4.6vw, 10svh), 4.25rem); }
.cta .sub { color: oklch(.86 0.0033 var(--nh)); }

/* ── Footer, on the ground ───────────────────────────────────────────────── */
.site-footer { padding-block: 1.25rem 2rem; border: 0; }
.footer-text p { color: var(--ink-3); }

/* Phones: one header row, a calmer headline. */
@media (max-width: 699px) {
  .site-header .header-row { padding-inline: 1rem .375rem; }
  .trio-item:nth-child(2) { transform: none; }
  .section { padding-block: calc(var(--inset) + var(--clear)) 3rem; }
}
@media (max-width: 699px) and (prefers-reduced-motion: no-preference) {
  .js .hero { height: 450svh; }
  .js .hero-stage { top: 0; height: 100svh; }
  .js .hero-copy { padding: calc(var(--header-h) + 6px + 1.5rem) 1.5rem 1.5rem; }
  .js .day-frame { bottom: calc(var(--inset) + 1rem); inset-inline: calc(var(--inset) + 1rem); }
}
@media (max-width: 699px) {
  /* No run: the promise sits above the photo, under the header. */
  .hero-frame { height: calc(100svh - 2 * var(--inset)); }
  .hero-copy { padding-block-start: calc(var(--header-h) + 6px + 1.5rem); color: var(--snow); }
}
@media (max-width: 520px) {
  .btn-sm { padding-inline: 1rem; font-size: .8125rem; }
  .lang { padding-inline: .65rem; }
  .brand-word { font-size: 1rem; }
  .hero .display, html[lang="ar"] .hero .display { font-size: 2.25rem; }
  .title { font-size: 1.875rem; }
  .hero .lede { font-size: 1rem; margin-block-start: .6rem; }
  .hero .cta-row { margin-block-start: 1rem; }
}

/* ── Device photos ────────────────────────────────────────────────────────────
   Product shots on a plain studio ground, Apple-style: a phone in one hand
   (How it works), a tablet in two hands (Security). Made in Figma's image
   generator with a flat green screen (website/review/devices), the screen
   then painted black; the real app's screen sits exactly on it. The photos
   are straight-on, so the screen is placed by percentages of the photo
   (measured from the green): it stays sharp and exact at every size. */
.dshot {
  position: relative;
  margin: 0;
}
/* Cut out of the studio background (tools/cutout.py): the device stands on the
   section itself. Where hands run out of the photo, they fade away softly. */
.dshot--phone .dshot-photo { -webkit-mask-image: linear-gradient(#000 74%, transparent 97%); mask-image: linear-gradient(#000 74%, transparent 97%); }
.dshot--tablet .dshot-photo { -webkit-mask-image: linear-gradient(#000 80%, transparent 99%); mask-image: linear-gradient(#000 80%, transparent 99%); }
.dshot-photo { display: block; width: 100%; height: auto; max-width: none; }
.dshot-screen {
  position: absolute;
  overflow: hidden;
  container-type: inline-size;
  background: var(--app-page); /* the app's own page colour, under its screens */
}
.dshot-screen > img, .mon-pane img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.dshot--phone .dshot-screen { left: 28.02%; top: 10.7%; width: 44.06%; height: 69.92%; border-radius: 10.6% / 5%; }
.dshot--phone .pane { position: absolute; inset: 0; }
.dshot--tablet .dshot-screen { left: 16.41%; top: 8.375%; width: 67.19%; height: 71.5%; border-radius: 1.4% / 2.1%; }

@media (min-width: 960px) {
  /* As tall as the window allows beside the four promises (photo 1.6:1). */
  .security .dshot--tablet { align-self: center; justify-self: center; width: min(100%, calc((100svh - 2 * var(--inset) - var(--clear) - 12.5rem) * 1.6)); }
}
.dshot--monitor .dshot-screen { left: 4.22%; top: 5.85%; width: 91.57%; height: 67.55%; border-radius: .4%; }
/* The Logs page is a little narrower than the monitor: it sits centred on the
   admin's own page colour, as the page would. */
/* Four admin pages, one per feature (main.js §3b): the shown one fades in. */
.dshot--monitor .mon-pane {
  position: absolute;
  inset: 0;
  display: block;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease, visibility 0s linear .3s;
}
.dshot--monitor[data-active="1"] .mon-pane[data-pane="1"],
.dshot--monitor[data-active="2"] .mon-pane[data-pane="2"],
.dshot--monitor[data-active="3"] .mon-pane[data-pane="3"],
.dshot--monitor[data-active="4"] .mon-pane[data-pane="4"] {
  opacity: 1;
  visibility: visible;
  transition: opacity .45s var(--ease), visibility 0s;
}
/* The features beside it are its tabs: the shown one is bright, its icon in
   the brand colour; the others wait a step back. */
.cap {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 2.75rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-3);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: color .2s ease;
}
.cap .icon { color: inherit; transition: color .2s ease; }
@media (hover: hover) { .cap:hover { color: var(--ink-2); } }
.cap.is-active { color: var(--ink); }
.cap.is-active .icon { color: var(--brand-on-dark); }
@media (prefers-reduced-motion: reduce) {
  .dshot--monitor .mon-pane, .cap, .cap .icon { transition: none; }
}

/* The phone's status bar, drawn over the app's own top margin (the screens
   are taken with an iPhone's safe areas), with the camera pill where the
   photo has it. */
.dshot-screen .sb {
  position: absolute;
  inset: 0 0 auto;
  z-index: 1;
  height: 12cqw;
  padding-inline: 6cqw;
  background: var(--app-bar);
  color: var(--app-ink);
  font-size: 4cqw;
}
.dshot-screen .sb-island { width: 27.4cqw; height: 8cqw; border-radius: 4cqw; background: var(--app-island); }
.dshot-screen .sb-icons { gap: 1.2cqw; }

.how .how-device { width: 100%; max-width: 26rem; margin-inline: auto; }
@media (min-width: 900px) {
  .how .how-device { width: min(26rem, calc((100svh - 2 * var(--inset) - var(--clear) - 3.5rem) * .75)); }
}
@media (prefers-reduced-motion: no-preference) {
  .how .how-device { will-change: transform; }
}
/* Phones: the devices come closer, so what is on their screens can be read.
   Hands and stands run off the sheet's edges; the screens stay whole. */
@media (max-width: 699px) {
  .how, .board, .security { overflow-x: clip; }
  .how .how-device { --w: min(135vw, 34rem); width: var(--w); max-width: none; margin-inline: calc((100% - var(--w)) / 2); }
  .board .dshot--monitor { width: calc(100% + 2 * var(--gutter) - 8px); margin-inline: calc(4px - var(--gutter)); }
  .security .dshot--tablet { --w: min(128vw, 34rem); width: var(--w); margin-inline: calc((100% - var(--w)) / 2); }
}

/* ── Skeleton screens ─────────────────────────────────────────────────────────
   While a photo or an app screen is still loading, its frame shows a calm
   placeholder in the sheet's own tint with a soft light passing over it
   (main.js §1c marks the frame ready once its picture has arrived). The phone
   screens draw the app's own outline (title, card, form, tab bar) behind the
   picture, so a slow connection still shows what is coming. */
/* (Every skeleton frame is already positioned and clips: the hero frame, the
   scenes; the phones get it here.) */
.handset { position: relative; overflow: hidden; }
.js [data-skeleton]:not(.is-ready) { background-color: var(--skeleton); border-radius: var(--r-card); }
.js [data-skeleton]:not(.is-ready)::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  background: linear-gradient(100deg, transparent 25%, var(--skeleton-hi) 50%, transparent 75%);
  transform: translateX(-100%);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .js [data-skeleton]:not(.is-ready)::after { animation: skeleton 1.4s cubic-bezier(.65, 0, .35, 1) infinite; }
}
@keyframes skeleton { to { transform: translateX(100%); } }
.handset img,
.shot--phone .pane {
  --sk: oklch(.9 0.0026 var(--nh));
  background:
    linear-gradient(var(--sk) 0 0) 7% 3% / 26% 1.4% no-repeat,
    linear-gradient(var(--sk) 0 0) 7% 6% / 46% 2.6% no-repeat,
    linear-gradient(var(--sk) 0 0) 50% 17% / 88% 13% no-repeat,
    linear-gradient(var(--sk) 0 0) 50% 39% / 88% 19% no-repeat,
    linear-gradient(var(--sk) 0 0) 50% 55% / 88% 5.5% no-repeat,
    linear-gradient(var(--sk) 0 0) 50% 96.5% / 92% 6.5% no-repeat,
    oklch(.97 0.0013 var(--nh));
}

/* ── Without JavaScript ───────────────────────────────────────────────────────
   The scenes need the script to fit the app's screen onto the photo, so without
   it the photo steps aside and the real screen shows on its own: the phone's
   first screen, the Logs table, the refused scan. (The header stays a solid
   pill: its see-through tone is set by the script.) */
html:not(.js) .shot { background: none; }
html:not(.js) .shot-stage > img,
html:not(.js) .shot-stage > picture { display: none; }
html:not(.js) .shot-ui { display: block; overflow: hidden; border-radius: var(--r-card); box-shadow: 0 0 0 1px var(--line); }
html:not(.js) .shot-ui img { display: block; width: 100%; height: auto; }
html:not(.js) .shot--phone .shot-ui { width: min(100%, 300px); margin-inline: auto; border-radius: 36px; box-shadow: 0 0 0 8px var(--night), 0 40px 70px -40px oklch(.25 .01 var(--nh) / .6); }
html:not(.js) .shot--phone .pane:not([data-pane="1"]),
html:not(.js) .ph-tap,
html:not(.js) .ph-cue { display: none; }

/* Short laptop windows (the founder's 1280 × 600): the promise rows a touch tighter. */
@media (min-width: 960px) and (max-height: 640px) { .security .tile { padding-block: .6rem; } .security .head { margin-block-end: 1rem; } }


/* ── The menu (where the nav does not fit) ────────────────────────────────────
   A button in the header pill (two lines that turn into a cross) opens the
   page's sections as a dark sheet just under it (main.js §2c): big links for
   thumbs, then the language and "Book a demo". Only with the script; without
   it the header keeps its language link and the page scrolls as ever. */
.menu-btn, .menu, .menu-scrim { display: none; }
html.menu-open { overflow: hidden; }
@media (max-width: 1079px) {
  .js .menu-btn {
    display: inline-grid;
    place-content: center;
    gap: 5px;
    flex: none;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    box-shadow: inset 0 0 0 1px var(--line-strong);
    color: var(--ink);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: box-shadow .25s ease, color .25s ease, scale .16s var(--ease);
  }
  .menu-btn:active { scale: .94; }
  .menu-btn span { display: block; width: 16px; height: 1.5px; border-radius: 1px; background: currentColor; transition: translate .35s var(--ease), rotate .35s var(--ease); }
  .menu-btn[aria-expanded="true"] span:first-child { translate: 0 3.25px; rotate: 45deg; }
  .menu-btn[aria-expanded="true"] span:last-child { translate: 0 -3.25px; rotate: -45deg; }

  .js .menu:not([hidden]), .js .menu-scrim:not([hidden]) { display: block; }
  .menu {
    --ink: var(--snow); --ink-2: oklch(.8 0.004 var(--nh)); --line: oklch(1 0 0 / .1);
    --pill: var(--snow); --pill-ink: var(--night); --pill-hover: oklch(.99 0.0013 var(--nh));
    position: absolute;
    top: calc(var(--header-h) + 8px);
    inset-inline: 0;
    width: calc(100% - 2 * var(--inset) - 8px);
    max-width: 76rem;
    max-height: calc(100svh - var(--header-top) - var(--header-h) - 8px - var(--inset));
    margin-inline: auto;
    padding: .375rem 1.25rem 1.25rem;
    overflow-y: auto;
    overscroll-behavior: contain;
    border-radius: var(--r-sheet);
    background: oklch(.2 0.0048 var(--nh));
    box-shadow: 0 0 0 1px oklch(1 0 0 / .08), 0 28px 56px -28px oklch(.1 0.004 var(--nh) / .8);
    color: var(--ink);
    pointer-events: auto;
    opacity: 0;
    translate: 0 -10px;
    scale: .98;
    transform-origin: 50% 0;
    transition: opacity .2s ease, translate .4s var(--ease), scale .4s var(--ease);
  }
  .menu.is-shown { opacity: 1; translate: 0 0; scale: 1; }
  .menu-links { margin: 0; padding: 0; list-style: none; }
  .menu-links li + li { border-block-start: 1px solid var(--line); }
  .menu-links a {
    display: flex;
    align-items: center;
    min-height: 3.75rem;
    color: var(--ink);
    font: 500 1.625rem/1.1 var(--font-display);
    letter-spacing: -.012em;
    text-transform: uppercase;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: color .15s ease;
  }
  .menu-links a:active { color: var(--ink-2); }
  html[lang="ar"] .menu-links a { font-size: 1.5rem; font-weight: 600; text-transform: none; letter-spacing: 0; }
  /* The links follow the sheet down one after another: one short cascade. */
  .menu-links li, .menu-foot { opacity: 0; translate: 0 8px; transition: opacity .3s ease, translate .45s var(--ease); }
  .menu.is-shown .menu-links li, .menu.is-shown .menu-foot { opacity: 1; translate: 0 0; }
  .menu.is-shown .menu-links li:nth-child(2) { transition-delay: 30ms; }
  .menu.is-shown .menu-links li:nth-child(3) { transition-delay: 60ms; }
  .menu.is-shown .menu-links li:nth-child(4) { transition-delay: 90ms; }
  .menu.is-shown .menu-links li:nth-child(5) { transition-delay: 120ms; }
  .menu.is-shown .menu-foot { transition-delay: 150ms; }
  .menu-foot {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-block-start: .25rem;
    padding-block-start: 1rem;
    border-block-start: 1px solid var(--line);
  }
  .menu-foot .lang { display: inline-flex; align-items: center; gap: .5rem; padding-inline: .5rem .75rem; color: var(--ink-2); }
  .menu-foot .btn { flex: 1; min-height: 3.25rem; }
  .menu-scrim {
    position: fixed;
    inset: 0;
    z-index: 19;
    background: oklch(.12 0.004 var(--nh) / .5);
    opacity: 0;
    transition: opacity .3s ease;
  }
  .menu-scrim.is-shown { opacity: 1; }
  /* While it is open the header pill is dark, whatever is under it. */
  .js .site-header.is-open[data-tone] .header-row {
    --ink: var(--snow); --ink-2: oklch(.8 0.004 var(--nh)); --ink-3: oklch(.66 0.0044 var(--nh)); --line-strong: oklch(1 0 0 / .2);
    --pill: var(--snow); --pill-ink: var(--night); --pill-hover: oklch(.99 0.0013 var(--nh));
    background: oklch(.2 0.0048 var(--nh));
    box-shadow: 0 0 0 1px oklch(1 0 0 / .08), 0 12px 32px -18px oklch(.15 0.0044 var(--nh) / .55);
  }
}
/* Phones: the language moves into the menu, so the pill keeps the name,
   "Book a demo" and the menu button. */
@media (max-width: 699px) {
  .js .header-actions > .lang { display: none; }
}
/* Narrow phones, or bigger text on any phone (measured in em, so it follows the
   reader's text size, not only the screen): the name, Book a demo and the menu
   button give a little room each; when even that is not enough, Book a demo
   leaves the pill (it is in the photo and in the menu). */
.site-header { container: bar / inline-size; }
@container bar (max-width: 22.4em) {
  .site-header .header-row { gap: .5rem; padding-inline: .875rem .3rem; }
  .site-header .brand-word { font-size: .9375rem; }
  .site-header .brand-mark { width: 20px; height: 20px; }
  .site-header .header-actions { gap: .25rem; }
  .header-actions .btn-sm { padding-inline: .75rem; font-size: .75rem; }
}
@container bar (max-width: 19.75em) {
  .js .header-actions .btn-sm { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .menu, .menu-scrim, .menu-links li, .menu-foot, .menu-btn span { transition: none; }
}

/* ── Phones: built for one hand ───────────────────────────────────────────────
   The gate photo fills the whole screen, also behind the browser's toolbar
   (lvh), so nothing is left blank when the toolbar shrinks away; what must be
   seen keeps clear of the toolbar (the difference, 100lvh - 100svh). The
   promise and "Book a demo" sit at the foot of the photo, where a thumb is,
   and the gate stays in view above them. */
@media (max-width: 699px) and (prefers-reduced-motion: no-preference) {
  .js .hero-stage { height: 100svh; height: 100lvh; }
  .js .hero + .section { margin-block-start: calc(-100svh + var(--inset)); margin-block-start: calc(-100lvh + var(--inset)); }
  /* The card holds no controls: taps go through its frame to "Book a demo". */
  .js .day-frame { bottom: calc(var(--inset) + 1rem + 100lvh - 100svh); pointer-events: none; }
  .js .hero-copy {
    top: auto;
    bottom: 0;
    inset-inline: 0;
    isolation: isolate;
    padding: 5rem 1.25rem calc(var(--inset) + 1.5rem + 100lvh - 100svh);
    text-align: center;
  }
  /* A soft dusk under the words, so they read on the paving. */
  .js .hero-copy::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(to top, oklch(.15 0.006 var(--nh) / .78), oklch(.15 0.006 var(--nh) / .5) 60%, oklch(.15 0.006 var(--nh) / 0));
    pointer-events: none;
  }
  .js .hero .lede { margin-inline: auto; }
  .js .hero .cta-row { justify-content: center; }
  .js .hero .cta-row .btn { width: 100%; max-width: 22rem; min-height: 3.25rem; }
}

@media (max-width: 699px) {
  /* Less empty sheet: still clear of the header pill when a section is
     reached from the menu. */
  .section { padding-block: calc(var(--inset) + 4.25rem) 2.5rem; }

  /* Your compound: the middle phone in the centre, its neighbours peeking in
     at both sides (main.js §3c); each one settles to the front as it reaches
     the centre. */
  .trio {
    --pw: calc(var(--ph) * .46875);
    padding-inline: calc(50% + var(--gutter) - var(--pw) / 2);
    scroll-padding-inline: 0;
  }
  .trio-item { scroll-snap-align: center; }

  /* The four things you set: two neat columns of icon and words, the same
     as the features under the monitor. No boxes, no lines. */
  .pills {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .25rem 1.25rem;
    margin-block-start: 1.5rem;
  }
  .pills li {
    justify-content: flex-start;
    gap: .625rem;
    min-height: 3rem;
    padding: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    color: var(--ink-2);
    font-size: .9375rem;
    line-height: 1.3;
  }
  .pills .icon { flex: none; width: 1.125rem; height: 1.125rem; color: var(--ink); }
}
@media (max-width: 699px) and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view(inline)) {
    .js .trio .handset { animation: trio-focus linear both; animation-timeline: view(inline); }
  }
}
@keyframes trio-focus {
  0%, 100% { scale: .9; opacity: .6; }
  50% { scale: 1; opacity: 1; }
}

/* ── Phones, round two ────────────────────────────────────────────────────────
   For management: the four features as two neat columns of plain tabs.
   Your compound: a thin line under the swipe row shows where you are among
   the three (scroll-driven; hidden where browsers can't). The
   day at the gate is a shorter run on phones (about 3 screens, was 4). */
.trio-progress { display: none; }
@media (max-width: 699px) {
  /* No boxes: two neat columns of plain tabs. The one on the monitor is
     bright with its icon in the brand blue; the others wait a step back. */
  .board .caps {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .25rem 1.25rem;
    margin-block-start: 1.5rem;
  }
  .board .caps li { display: block; min-width: 0; }
  .board .cap {
    display: flex;
    width: 100%;
    min-height: 3rem;
    gap: .625rem;
    font-size: .9375rem;
    line-height: 1.3;
    text-align: start;
    -webkit-tap-highlight-color: transparent;
  }
  .board .cap .icon { flex: none; width: 1.125rem; height: 1.125rem; }
}
@media (max-width: 699px) and (prefers-reduced-motion: no-preference) {
  .js .hero { height: 380svh; }
  @supports (animation-timeline: scroll(inline)) {
    .tailored .wrap { timeline-scope: --trio; }
    .trio { scroll-timeline: --trio inline; }
    .trio-progress {
      --dir: 1;
      display: block;
      position: relative;
      width: 4.5rem;
      height: 2px;
      margin: 1rem auto 0;
      border-radius: 1px;
      background: var(--line);
      overflow: hidden;
    }
    html[dir="rtl"] .trio-progress { --dir: -1; }
    .trio-progress span {
      position: absolute;
      inset-block: 0;
      inset-inline-start: 0;
      width: 33.334%;
      border-radius: inherit;
      background: var(--ink);
      animation: trio-progress linear both;
      animation-timeline: --trio;
    }
  }
}
@keyframes trio-progress {
  from { translate: 0 0; }
  to { translate: calc(var(--dir) * 200%) 0; }
}

/* ── Touch: controls behave like controls ─────────────────────────────────────
   Every hover above waits for a mouse ((hover: hover) and (pointer: fine)), so a
   tap never leaves a step or a link lit. Holding a finger on a button does not
   select its words or open the link menu; text that is content stays
   selectable. (mobile-native skill) */
button, .btn, .cap, .menu-btn, .step, .lang {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
/* A finger gets an answer the moment it lands, not when it lifts. */
.step:active { background: oklch(.5 0.0088 var(--nh) / .08); }
.cap:active { color: var(--ink); }

/* A narrow card (the smallest phones, or bigger text): the pass's chip moves
   under the name, so the name keeps a readable line instead of one word each. */
.moment { container-type: inline-size; }
@container (max-width: 19em) {
  .moment-pass { grid-template-columns: auto minmax(0, 1fr); row-gap: .5rem; }
  .moment-pass .chip { grid-column: 2; justify-self: start; }
}

/* Words on photos stay readable wherever the light falls (measured from the
   pixels behind them, worst 5 %): a soft shade sits behind the closing words,
   where the night gate's lamps shine, and behind the promise on laptops,
   where the sky is bright. */
.cta .wrap { z-index: 1; }
.cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 75% 60% at 50% 50%, oklch(.12 0.006 var(--nh) / .62), oklch(.12 0.006 var(--nh) / 0) 78%);
  pointer-events: none;
}
.cta .sub { color: oklch(.93 0.0026 var(--nh)); }
@media (max-width: 699px) {
  .cta::after { background: radial-gradient(ellipse 95% 60% at 50% 50%, oklch(.12 0.006 var(--nh) / .72), oklch(.12 0.006 var(--nh) / 0) 85%); }
}
@media (min-width: 700px) {
  .hero-copy { isolation: isolate; }
  .hero-copy::before {
    content: "";
    position: absolute;
    inset: -2rem -4rem;
    z-index: -1;
    background: radial-gradient(ellipse 60% 60% at 50% 50%, oklch(.15 0.006 var(--nh) / .42), oklch(.15 0.006 var(--nh) / 0) 100%);
    pointer-events: none;
  }
}

/* ── The other pages: Book a demo, Privacy ────────────────────────────────────
   One light sheet on the ground, under the floating header, like the home
   page's sheets. No boxes: the form's fields sit straight on the sheet. */
.subpage { padding-block-start: var(--inset); }
.subpage .section { min-height: calc(100svh - 2 * var(--inset)); }
.footer-meta a { color: inherit; text-decoration: underline; text-underline-offset: .2em; }
@media (hover: hover) and (pointer: fine) { .footer-meta a:hover { color: var(--ink); } }

/* Book a demo: title, form, then what happens next on phones; on wide screens
   the words on the reading side and the form beside them. */
.book-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "head" "panel" "next";
  gap: 2rem;
  max-width: 34rem;
}
.book-head { grid-area: head; }
.book-head .sub { margin-inline: 0; }
.book-panel { grid-area: panel; }
.book-next { grid-area: next; display: grid; gap: 1.25rem; margin: 0; padding: 1.5rem 0 0; list-style: none; border-block-start: 1px solid var(--line); }
.book-next li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 1rem; align-items: start; }
@media (min-width: 900px) {
  .book-grid {
    grid-template-columns: minmax(0, 24rem) minmax(0, 30rem);
    grid-template-areas: "head panel" "next panel";
    align-content: start;
    justify-content: center;
    column-gap: clamp(3rem, 8vw, 7rem);
    row-gap: 2.5rem;
    max-width: none;
  }
  .book-head { align-self: end; }
  .book-next { align-self: start; }
}

/* The form. */
.book-form { display: grid; gap: 1.5rem; }
.book-form[hidden] { display: none; }
.field { display: grid; gap: .5rem; min-width: 0; margin: 0; padding: 0; border: 0; }
.field > label, .field > legend { padding: 0; color: var(--ink); font-size: .9375rem; font-weight: 600; }
.field .optional { color: var(--ink-3); font-weight: 400; }
.field-hint { margin: 0; color: var(--ink-3); font-size: .8125rem; }
.field-err { margin: 0; color: var(--refused); font-size: .875rem; font-weight: 500; }
.field-err:empty { display: none; }
.book-form input[type="text"],
.book-form input[type="tel"] {
  width: 100%;
  min-height: 3.25rem;
  padding: .75rem 1rem;
  border: 0;
  border-radius: 14px;
  background: var(--sheet);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--ink);
  font: inherit;
  font-size: 1rem; /* 16 px: phones do not zoom in on the field */
  transition: box-shadow .15s ease;
}
.book-form input[type="text"]:focus,
.book-form input[type="tel"]:focus { outline: none; box-shadow: inset 0 0 0 2px var(--brand); }
.book-form input[aria-invalid] { box-shadow: inset 0 0 0 2px var(--refused); }
html[dir="rtl"] .book-form input[type="tel"] { text-align: end; }

/* Choices as pills you tap: the chosen one fills with the brand blue. */
.choices { display: flex; flex-wrap: wrap; gap: .5rem; }
.choice { position: relative; display: inline-flex; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.choice input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.choice span {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: .5rem 1.05rem;
  border-radius: 999px;
  background: var(--sheet);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--ink-2);
  font-size: .9375rem;
  font-weight: 500;
  -webkit-user-select: none;
  user-select: none;
  transition: background-color .15s ease, color .15s ease, box-shadow .15s ease, scale .16s var(--ease);
}
.choice input:checked + span { background: var(--brand); box-shadow: none; color: var(--sheet); }
.choice input:focus-visible + span { outline: 3px solid var(--brand); outline-offset: 2px; }
.choice:active span { scale: .97; }
@media (hover: hover) and (pointer: fine) { .choice:hover input:not(:checked) + span { color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink-3); } }
fieldset[aria-invalid] .choice span { box-shadow: inset 0 0 0 1px var(--refused); }

.form-submit { width: 100%; min-height: 3.25rem; margin-block-start: .25rem; }
.form-note { margin: -.5rem 0 0; color: var(--ink-3); font-size: .8125rem; text-align: center; }
.form-note a, .book-done a, .doc a { color: var(--brand); text-decoration: underline; text-underline-offset: .2em; }

/* After sending: a calm note in the form's place. */
.book-done { display: grid; justify-items: center; gap: .75rem; padding-block: 1rem; text-align: center; outline: none; }
.book-done[hidden] { display: none; }
.book-done-mark .icon { width: 3rem; height: 3rem; color: var(--brand); }
.book-done-title { font: 600 1.5rem/1.2 var(--font-display); }
html[lang="en"] .book-done-title { text-transform: uppercase; font-weight: 500; letter-spacing: -.012em; }
.book-done p { max-width: 26rem; margin: 0; color: var(--ink-2); }
.book-done .btn { margin-block-start: .5rem; }
@media (prefers-reduced-motion: no-preference) {
  .book-done:not([hidden]) { animation: done-in .45s var(--ease) both; }
}
@keyframes done-in { from { opacity: 0; translate: 0 10px; } to { opacity: 1; translate: 0 0; } }

/* Privacy: one readable column. */
.doc-wrap { max-width: 42rem; }
.doc-head { margin-block-end: 2.5rem; }
.doc-head .sub { margin-inline: 0; }
.doc-updated { margin-block-start: .75rem; color: var(--ink-3); font-size: .875rem; }
.doc section + section { margin-block-start: 2rem; }
.doc h2 { margin-block-end: .5rem; font: 600 1.125rem/1.35 var(--font-display); }
.doc p { color: var(--ink-2); line-height: 1.65; }
.doc p + p { margin-block-start: .75rem; }

/* Page not found: the title, one line, two ways on, in the middle of the sheet. */
.notfound .wrap { display: grid; justify-items: center; align-content: center; min-height: 60svh; text-align: center; }
.notfound .cta-row { justify-content: center; }
