/*
 * Pabasa's public page.
 *
 * This adopts the Statotech website's design system rather than the product's own. The page lives
 * in the company's marketing estate, next to statotec.com, so it uses that system's vocabulary:
 * near-black ink surfaces, full-bleed colour blocking through surface-scoped --s-* tokens, a fluid
 * clamp() type scale, Inter Tight set tight at display sizes, numbered mono eyebrows. Token names
 * match /home/b/projects/statotech/website/app/globals.css so the two can be read side by side.
 *
 * TWO DELIBERATE DEPARTURES FROM THE WEBSITE:
 *
 * 1. Mint is rationed. The company site uses #3DDC97 as its house accent and uses it freely; here
 *    it means ONE thing — "this is the control you press" — plus the two places it carries the
 *    Confirmed state (the live fix on the map, the good pip). It is never a heading colour and
 *    never decoration. Asked for directly: too much green.
 *
 * 2. There is a geo ramp, and it does the work mint used to. This product is about location, so
 *    the informational colour is the blue of a map: rings, fences, chart lines, heading accents.
 *    Neither the website nor packages/brand has a mid-blue — the website jumps from #143466 to
 *    mint, and the product ramp is tuned for UI chrome — so the ramp below is derived from the
 *    brand navy specifically for maps and charts. --geo-cyan is the website's own --accent-bright,
 *    reused for the live-signal glow because a GPS reading should read as a signal, not as foliage.
 *
 * The verdict tiers are not ours to choose. Those four colours, labels and sentences are product
 * facts, so they come from the generated tokens.css (--fp-tier-*) exactly as the handset and the
 * dashboard get them, and packages/brand's drift test fails if either copy is hand-edited.
 *
 * --brand is #143466, the ST mark's own colour: the dominant pixel of
 * packages/brand/assets/statotech-mark.png is #133466. packages/brand declares #0e436e for the
 * same thing and calls it "sampled from the mark itself"; that description does not hold. The
 * website's value is the one that matches the artwork, and nothing here reads the product's brand
 * token — only its tier tokens.
 */

/* ─── Tokens ─────────────────────────────────────────────────────────────── */
:root {
  --ink:            #0A0C10;
  --ink-2:          #12161D;
  --ink-3:          #1B212B;

  --paper:          #FFFFFF;
  --paper-2:        #F7F8FA;
  --paper-3:        #EFF1F5;

  --brand:          #143466;

  /* Action only. */
  --accent:         #3DDC97;
  --accent-hi:      #5FE8AB;
  --accent-deep:    #0B6B4A;
  --accent-on:      #04241A;

  /* Information: maps, fences, chart marks, heading accents. Derived from --brand.
     --geo-600 measures 6.4:1 on paper and --geo-300 measures 10:1 on ink, so both carry text. */
  --geo-100:        #E7F0FA;
  --geo-200:        #C7DDF2;
  --geo-300:        #93BFE4;
  --geo-400:        #5B9BD5;
  --geo-600:        #1F5FA8;
  --geo-800:        #143466;
  --geo-cyan:       #6EE7FF;

  --text:           #0A0C10;
  --text-2:         #4C5563;
  --text-muted:     #666F7B;

  --rule:           rgba(10, 12, 16, 0.10);
  --rule-strong:    rgba(10, 12, 16, 0.20);

  /* Fluid type, 360px → 1600px */
  --t-xs:      0.75rem;
  --t-sm:      0.8125rem;
  --t-base:    clamp(0.9375rem, 0.91rem + 0.14vw, 1rem);
  --t-md:      clamp(1rem,      0.96rem + 0.22vw, 1.125rem);
  --t-lg:      clamp(1.0625rem, 0.98rem + 0.42vw, 1.3125rem);
  --t-xl:      clamp(1.25rem,   1.06rem + 0.95vw, 1.75rem);
  --t-2xl:     clamp(1.75rem,   1.32rem + 2.1vw,  3rem);
  --t-display: clamp(2.375rem,  1.42rem + 4.7vw, 4.5rem);

  --tr-display: -0.035em;
  --tr-heading: -0.025em;
  --tr-caps:     0.12em;

  --lh-display: 1.03;
  --lh-heading: 1.12;
  --lh-body:    1.65;

  --s-1: 0.25rem;  --s-2: 0.5rem;  --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;    --s-7: 3rem;     --s-8: 4rem;
  --s-9: 5rem;     --s-10: 6rem;

  --section-pad: clamp(3.5rem, 6.2vw, 6.75rem);
  --gutter:      clamp(1.25rem, 4vw, 3rem);
  --container:   79rem;

  --r-1: 4px; --r-2: 8px; --r-3: 12px; --r-4: 20px; --r-pill: 999px;

  --sh-3: 0 2px 4px rgba(10, 12, 16, 0.06), 0 34px 60px -20px rgba(10, 12, 16, 0.22);

  --font-display: 'Inter Tight', ui-sans-serif, system-ui, sans-serif;
  --font-body:    'Inter', ui-sans-serif, system-ui, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --dur: 0.24s;
  --ease: cubic-bezier(0.2, 0, 0, 1);

  /* Surface-scoped defaults — a paper surface. --s-em is the heading accent. */
  --s-bg:     var(--paper);
  --s-text:   var(--text);
  --s-text-2: var(--text-2);
  --s-muted:  var(--text-muted);
  --s-rule:   var(--rule);
  --s-accent: var(--geo-600);
  --s-em:     var(--geo-600);
}

/* ─── Surfaces ───────────────────────────────────────────────────────────── */
/* A section declares its surface and everything inside adapts. This is what makes full-bleed
   colour blocking possible without a second copy of every component. */

.surface-paper   { background: var(--paper);   --s-bg: var(--paper); }
.surface-paper-2 { background: var(--paper-2); --s-bg: var(--paper-2); }

.surface-ink {
  background: var(--ink);
  --s-bg:     var(--ink);
  --s-text:   #F5F7FA;
  --s-text-2: #AFB8C4;
  --s-muted:  #79838F;
  --s-rule:   rgba(255, 255, 255, 0.11);
  --s-accent: var(--geo-300);
  --s-em:     var(--geo-300);
  color: var(--s-text-2);
}

.surface-brand {
  background: var(--brand);
  --s-bg:     var(--brand);
  --s-text:   #F4F7FC;
  --s-text-2: #C3D2E7;
  --s-muted:  #93A6C4;
  --s-rule:   rgba(255, 255, 255, 0.17);
  --s-accent: var(--geo-300);
  --s-em:     var(--geo-300);
  color: var(--s-text-2);
}

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

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: var(--lh-body);
  color: var(--text-2);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* The mark, defined once at the top of the document and drawn with <use>. It must stay in the
   layout (not display:none) or the reference resolves to nothing in some engines. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
  color: var(--s-text);
  text-wrap: balance;
}

h1 {
  font-size: var(--t-display);
  font-weight: 700;
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
}

h2 { font-size: var(--t-2xl); max-width: 30ch; }
h3 { font-size: var(--t-md); font-weight: 600; }

/* One word of each display heading carries the accent — the house signature. It is the geo blue,
   not mint: mint is reserved for controls. */
h1 em, h2 em { font-style: normal; color: var(--s-em); }

p { margin: 0; text-wrap: pretty; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }
code { font-family: var(--font-mono); }

::selection { background: var(--accent); color: var(--accent-on); }

:focus-visible { outline: 2px solid var(--geo-600); outline-offset: 3px; border-radius: var(--r-1); }
.surface-ink :focus-visible,
.surface-brand :focus-visible,
.band-photo :focus-visible { outline-color: var(--geo-cyan); }

.skip {
  position: absolute;
  left: var(--s-4);
  top: -6rem;
  z-index: 20;
  padding: var(--s-3) var(--s-5);
  background: var(--accent);
  color: var(--accent-on);
  border-radius: var(--r-2);
  font-weight: 600;
  transition: top var(--dur) var(--ease);
}
.skip:focus { top: var(--s-4); }

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

/* ─── Eyebrow ────────────────────────────────────────────────────────────── */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--s-muted);
}

.eyebrow.num { gap: var(--s-4); }

/* The number, then a rule, then the label — the company site's numbered-section device. */
.eyebrow.num > span:first-child {
  position: relative;
  padding-right: var(--s-6);
  color: var(--s-accent);
}
.eyebrow.num > span:first-child::after {
  content: '';
  position: absolute;
  right: var(--s-2);
  top: 50%;
  width: var(--s-4);
  height: 1px;
  background: var(--s-rule);
}

.pip {
  width: 0.4375rem;
  height: 0.4375rem;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(61, 220, 151, 0.18);
}
/* The only other colour this page introduces. A build-status pip must not be mint — mint means
   "press this" — and the product's amber ramp is a warm brown that goes muddy on ink. Status
   only; never in text, never on a control. */
.pip-amber {
  background: #F6C05A;
  box-shadow: 0 0 0 3px rgba(246, 192, 90, 0.18);
}

/* ─── Buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.8125rem var(--s-5);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: -0.005em;
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) { .btn:hover { transform: none; } }

.btn-sm { padding: 0.5rem var(--s-4); }
.btn-lg { padding: 0.9375rem var(--s-6); font-size: var(--t-base); }

.btn-accent { background: var(--accent); color: var(--accent-on); }
.btn-accent:hover { background: var(--accent-hi); }

.btn-outline { color: var(--s-text); border-color: var(--s-rule); background: transparent; }
.btn-outline:hover { border-color: var(--s-accent); color: var(--s-accent); }

.cta-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* ─── Header ─────────────────────────────────────────────────────────────── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(10, 12, 16, 0.84);
  backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid var(--s-rule);
}

.header-inner { display: flex; align-items: center; gap: var(--s-6); min-height: 4.25rem; }
.header-actions { display: flex; align-items: center; gap: var(--s-3); }

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.5625rem;
  font-family: var(--font-display);
  font-size: 1.1875rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--s-text);
}

.wordmark-mark { width: 1.5rem; height: 1.5rem; color: var(--s-text); flex: none; }

.site-header nav { display: flex; gap: var(--s-5); margin-inline-start: auto; font-size: var(--t-sm); }
.site-header nav a { color: var(--s-text-2); }
.site-header nav a:hover { color: var(--s-accent); }

/* 52rem, not 70rem. The five labels, the wordmark and the button measure about 805px together,
   so dropping the nav at 1120px threw away in-page navigation on every tablet and every phone in
   landscape for no reason. Below 52rem there is genuinely no room, and a 5-section linear page
   does not warrant a JavaScript menu. */
@media (max-width: 52rem) {
  .site-header nav { display: none; }
  .header-actions { margin-inline-start: auto; }
}

/* ─── Hero ───────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  padding-top: clamp(2.5rem, 5vw, 4.5rem);
  padding-bottom: var(--s-7);
  overflow: hidden;
}

/* A cool wash behind the copy — the same device as the company site's hero, in the geo hue
   rather than mint. */
.hero::before {
  content: '';
  position: absolute;
  inset: -25% 42% 25% -22%;
  background: radial-gradient(closest-side, rgba(31, 95, 168, 0.30), transparent 76%);
  pointer-events: none;
}

.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1.06fr;
  gap: clamp(var(--s-6), 4.5vw, var(--s-9));
  align-items: center;
}

.hero-copy > * + * { margin-top: var(--s-5); }
.hero-copy .lede { max-width: 36ch; }

.lede { font-size: var(--t-lg); color: var(--s-text-2); }
.section-lede { font-size: var(--t-md); color: var(--s-text-2); max-width: 64ch; }

.hero-stats {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
  gap: var(--s-6);
  margin: var(--s-7) 0 0;
  padding-top: var(--s-5);
  border-top: 1px solid var(--s-rule);
}
.hero-stats dt {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--s-muted);
}
.hero-stats dd {
  margin: var(--s-2) 0 0;
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--s-text);
}
.hero-stats dd span {
  display: block;
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 400;
  color: var(--s-muted);
}

@media (max-width: 62rem) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-copy .lede { max-width: 48ch; }
  .hero::before { inset: -20% 10% 40% -20%; }
}
@media (max-width: 34rem) {
  .hero-stats { grid-template-columns: 1fr 1fr; gap: var(--s-4) var(--s-5); }
}

/* ─── The geofence panel ─────────────────────────────────────────────────── */
.geo { margin: 0; }

.geo-panel {
  position: relative;
  /* Matches the base image exactly, so the SVG overlay and the photograph crop identically and
     every ring stays on the feature it was measured against. */
  aspect-ratio: 1400 / 1100;
  border-radius: var(--r-4);
  overflow: hidden;
  border: 1px solid var(--s-rule);
  box-shadow: var(--sh-3);
}

.geo-base,
.geo-overlay { position: absolute; inset: 0; width: 100%; height: 100%; }
.geo-base { object-fit: cover; }

/* Geometry. Cyan reads as an instrument over a dusty aerial; mint would read as vegetation. */
.ring-eff {
  fill: none;
  stroke: var(--geo-cyan);
  stroke-width: 2.5;
  stroke-dasharray: 14 10;
  opacity: 0.9;
}
.ring-shop {
  fill: rgba(110, 231, 255, 0.06);
  stroke: var(--geo-cyan);
  stroke-width: 2;
  opacity: 0.75;
}
/* Barely a tint. At 0.16 the wash read as a swimming pool on the roof; the footprint should be
   an outline with a hint of fill, not a painted shape. */
.footprint {
  fill: rgba(110, 231, 255, 0.07);
  stroke: #FFFFFF;
  stroke-width: 2.5;
  stroke-dasharray: 10 8;
  opacity: 0.9;
}
.acc-edge { fill: none; stroke: var(--geo-cyan); stroke-width: 2; stroke-dasharray: 5 6; opacity: 0.8; }

/* The live fix is the one place on the map that carries the Confirmed state, so it is mint. */
.fix-dot { fill: var(--accent); stroke: #0A0C10; stroke-width: 3.5; }

/* Sized in the overlay's 1400-unit space. The panel renders around 600px wide, so 30 units is
   about 13px on screen — anything smaller is unreadable on the photograph. */
.geo-labels text {
  font-family: var(--font-mono);
  font-size: 30px;
  font-weight: 500;
  fill: #FFFFFF;
  /* A halo, so a label stays readable over a corrugated roof. */
  paint-order: stroke fill;
  stroke: rgba(10, 12, 16, 0.88);
  stroke-width: 7;
  stroke-linejoin: round;
}
.geo-labels .fix-label { text-anchor: middle; font-size: 27px; }
/* Anchored at its end, so the text grows away from the ring rather than back across it. */
.geo-labels .label-eff { text-anchor: end; }
.geo-labels .label-eff-sm,
.geo-labels .label-shop-sm,
.geo-labels .leader-shop-sm { display: none; }
.geo-labels .leader { stroke: #FFFFFF; stroke-width: 2; opacity: 0.65; }
.geo-labels .leader-eff { stroke-dasharray: 8 7; }
/* The rings are centred on the shop, not on the phone — the crosshair says which point they
   belong to, and is drawn as a cross so it cannot be mistaken for the fix dot. */
.geo-labels .centre-mark { stroke: #FFFFFF; stroke-width: 2.5; opacity: 0.55; fill: none; }

/* HUD blocks. Real text over the map, not baked into the image. */
.hud {
  position: absolute;
  background: rgba(10, 12, 16, 0.82);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--r-2);
}

.hud-verdict {
  top: var(--s-3);
  right: var(--s-3);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  /* Content-width, so it must be told not to grow past its own panel on a narrow viewport. */
  max-width: calc(100% - var(--s-6));
  padding: 0.5rem 0.75rem;
  font-size: var(--t-sm);
  color: #F5F7FA;
}
.hud-verdict strong { font-weight: 600; }
.hud-verdict .hud-sub { color: #9AA4B0; font-size: var(--t-xs); }
.hud-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--r-pill);
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(61, 220, 151, 0.22);
  flex: none;
}

/* One thin strip, not a block: four items across keeps the pavement and the road visible, which
   is what makes the panel read as a real place rather than a diagram. */
.hud-readout {
  right: var(--s-3);
  bottom: var(--s-3);
  left: var(--s-3);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem 0.875rem;
  margin: 0;
  padding: 0.625rem 0.875rem;
}
@media (max-width: 30rem) { .hud-readout { grid-template-columns: repeat(2, 1fr); } }

/* ── The panel on a phone ──
   The overlay's text is sized in viewBox units, so it shrinks with the panel: 30 units is ~13px
   on a desktop panel but ~7px on a 350px-wide one, which is unreadable. Scale the units up
   instead of letting the map become decoration.

   The HUD also has to give the map back its room. The readout drops to the two facts that are
   about THIS check-in being trustworthy, and the timestamp leaves the chip — the coordinate and
   the corroboration are instrument dressing here, and both are stated in the body copy below
   rather than only on the picture. */
@media (max-width: 34rem) {
  .geo-labels text { font-size: 46px; stroke-width: 10; }
  .geo-labels .fix-label { font-size: 42px; }
  .geo-labels .label-eff { display: none; }
  .geo-labels .label-eff-sm { display: block; }
  .geo-labels .label-shop,
  .geo-labels .leader-shop { display: none; }
  .geo-labels .label-shop-sm,
  .geo-labels .leader-shop-sm { display: block; }
  .hud-verdict .hud-sub { display: none; }
  .hud-readout div:nth-child(1),
  .hud-readout div:nth-child(3) { display: none; }
}
.hud-readout dt {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #79838F;
}
/* 11px, not 12: at --t-xs a coordinate pair wrapped onto a second line in every column and the
   strip grew tall enough to eat the pavement. */
.hud-readout dd {
  margin: 0.125rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  color: #E6EAF0;
  line-height: 1.4;
}

.geo figcaption {
  margin-top: var(--s-4);
  font-size: var(--t-sm);
  color: var(--s-muted);
  max-width: 52ch;
}
.geo figcaption code { color: var(--s-text-2); }

/* ─── Hero signal rail ───────────────────────────────────────────────────── */
.hero-rail {
  position: relative;
  margin-top: clamp(var(--s-7), 5vw, var(--s-9));
  padding-top: var(--s-5);
  border-top: 1px solid var(--s-rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-5);
}

.rail-label {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--s-muted);
}

.hero-rail ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-sm);
  color: var(--s-text-2);
}
.hero-rail li { display: flex; align-items: center; gap: var(--s-2); }
.hero-rail li::before {
  content: '';
  width: 0.3125rem;
  height: 0.3125rem;
  border-radius: var(--r-pill);
  background: var(--geo-400);
  flex: none;
}
/* GPS is the base proof, not one option among five. */
.hero-rail li.is-base { color: var(--s-text); font-weight: 500; }
.hero-rail li.is-base::before { background: var(--geo-cyan); box-shadow: 0 0 0 3px rgba(110, 231, 255, 0.18); }

.rail-note {
  flex: 1 1 18rem;
  font-size: var(--t-xs);
  color: var(--s-muted);
  text-align: right;
}
@media (max-width: 62rem) { .rail-note { text-align: left; } }

/* ─── Bands ──────────────────────────────────────────────────────────────── */
.band { padding-block: var(--section-pad); }
.band > .container > .eyebrow { margin-bottom: var(--s-4); }
.band h2 + .section-lede { margin-top: var(--s-5); }


/* ─── Section decoration ─────────────────────────────────────────────────── */
/* Backgrounds rather than more words. Two motifs, both drawn in CSS: concentric
   rings, which are the hero's geofence echoed at the edge of a section, and a
   map graticule. Each sits in a pseudo-element behind a raised .container, so
   decoration can never land on top of text or steal a click. */

.band { position: relative; isolation: isolate; overflow: hidden; }
.band > .container { position: relative; z-index: 1; }

/* Signal rings, bleeding off the top-right corner. repeating-radial-gradient
   gives evenly spaced hairlines; the mask fades them out before they reach the
   copy, so there is no hard edge to notice. */
.bg-rings::before {
  content: '';
  position: absolute;
  z-index: 0;
  top: -18rem;
  right: -16rem;
  width: 52rem;
  height: 52rem;
  background: repeating-radial-gradient(circle at 50% 50%,
    transparent 0 3.25rem, currentColor 3.25rem calc(3.25rem + 1px));
  color: var(--geo-400);
  opacity: 0.3;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 40%, transparent 72%);
  mask-image: radial-gradient(circle at 50% 50%, #000 40%, transparent 72%);
  pointer-events: none;
}
.surface-brand.bg-rings::before { color: #FFFFFF; opacity: 0.16; }

/* Map graticule. 1px lines on a 4.5rem pitch, faded from the top so the grid is
   felt at the section edge and gone by the time the copy starts. */
.bg-grid::before {
  content: '';
  position: absolute;
  z-index: 0;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--geo-200) 1px, transparent 1px),
    linear-gradient(to bottom, var(--geo-200) 1px, transparent 1px);
  background-size: 4.5rem 4.5rem;
  opacity: 0.4;
  -webkit-mask-image: linear-gradient(to bottom, #000, transparent 55%);
  mask-image: linear-gradient(to bottom, #000, transparent 55%);
  pointer-events: none;
}

/* ─── 01 The three cases ─────────────────────────────────────────────────── */
.cases {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: var(--s-5);
  margin: var(--s-8) 0 0;
  padding: 0;
  list-style: none;
}

.cases > li {
  display: grid;
  gap: var(--s-3);
  justify-items: start;
  padding: var(--s-5);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
}

.cases h3 { margin: 0; }
.cases p { color: var(--text-2); font-size: var(--t-sm); }

/* The little plan views. Same aerial, same centre, in all three — the circle is the only
   thing allowed to differ, which is what makes them a comparison rather than three pictures.
   Overlay coordinates are the crop's own pixel space and .case-panel is locked to its aspect
   ratio, so the geometry stays on the building it was measured against. */
.case-panel {
  position: relative;
  /* Explicit, because every child is absolutely positioned: the panel has no intrinsic width to
     derive a height from, and the parent grid uses justify-items: start so it does not get one. */
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--r-2);
  overflow: hidden;
  background: var(--paper-3);
}
.case-panel img,
.case-panel svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.case-panel img { object-fit: cover; }

/* The roofs are bright corrugated iron in full sun; without a little ink under it the cyan
   has nothing to read against. */
.k-scrim { fill: #0A0C10; opacity: 0.22; }

.k-fence { fill: none; stroke: var(--geo-cyan); stroke-width: 6; stroke-dasharray: 22 16; }
.k-shop  { fill: rgba(110, 231, 255, 0.08); stroke: #FFFFFF; stroke-width: 5; stroke-dasharray: 16 12; }

/* The halo is the point of the whole section: a phone less sure of itself draws a bigger one,
   and the fence follows. fill-opacity, not opacity, so its edge stays crisp over the roof. */
.k-halo {
  fill: var(--geo-cyan);
  /* Barely a tint. At 0.22 the large halo covered most of the panel and flattened the
     photograph into a blue blob; the dashed edge is what has to carry it. */
  fill-opacity: 0.1;
  stroke: var(--geo-cyan);
  stroke-width: 5;
  stroke-dasharray: 12 10;
}
.k-halo.is-out { fill: #F6C05A; fill-opacity: 0.16; stroke: #F6C05A; }

/* The dot takes the outcome's colour, so a mint dot never sits inside an amber halo. */
.k-dot { fill: var(--accent); stroke: #0A0C10; stroke-width: 5; }
.k-dot.is-out { fill: #F6C05A; }

/* ─── Verdict colours ────────────────────────────────────────────────────── */
/* The only place this page reads the product's own tokens. These four pairings are
   contrast-audited in packages/brand; nothing here fades or tints them. They dress the
   chips in 01, in the day table and in its legend — the four big definition cards that
   used to carry them were a glossary and have gone. */
.tier-verified   { color: var(--fp-tier-verified-fg);   background: var(--fp-tier-verified-bg);   border-color: var(--fp-tier-verified-border); }
.tier-probable   { color: var(--fp-tier-probable-fg);   background: var(--fp-tier-probable-bg);   border-color: var(--fp-tier-probable-border); }
.tier-unverified { color: var(--fp-tier-unverified-fg); background: var(--fp-tier-unverified-bg); border-color: var(--fp-tier-unverified-border); }
.tier-rejected   { color: var(--fp-tier-rejected-fg);   background: var(--fp-tier-rejected-bg);   border-color: var(--fp-tier-rejected-border); }

/* ─── 03/05 Claims ───────────────────────────────────────────────────────── */
/* A bold statement and one short line, four or five words apart. It replaced
   four paragraphs that said the same thing at ten times the length. */
.claims {
  display: grid;
  /* 12rem, not 15rem: with a 2rem gap, 15rem tracks only fitted three across the
     64rem measure and left the fourth claim orphaned on its own row. */
  grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
  gap: var(--s-5) var(--s-6);
  margin: var(--s-8) 0 0;
  padding: 0;
  list-style: none;
  max-width: 68rem;
}

.claims > li {
  display: grid;
  gap: var(--s-2);
  padding-top: var(--s-4);
  border-top: 1px solid var(--s-rule);
}
.claims strong {
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: var(--tr-heading);
  color: var(--s-text);
}
.claims span { font-size: var(--t-sm); color: var(--s-text-2); }

/* On the privacy surface each claim is a promise, so it gets a tick. */
.claims-check > li {
  border-top: none;
  padding: 0 0 0 var(--s-7);
  position: relative;
}
.claims-check > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.1em;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid var(--s-rule);
}
.claims-check > li::after {
  content: '';
  position: absolute;
  left: 0.5rem;
  top: 0.62em;
  width: 0.375rem;
  height: 0.22rem;
  border-left: 1.5px solid var(--geo-300);
  border-bottom: 1.5px solid var(--geo-300);
  transform: rotate(-45deg);
}

/* ─── The shift window ───────────────────────────────────────────────────── */
/* The privacy claim drawn instead of argued. All three rows share one column template, so
   the labels, the bars and the times stay locked to each other; the ratios are the real
   proportions of a 24-hour day, which is why the lit band is the length it is. */
.shift {
  display: grid;
  gap: var(--s-2);
  margin: var(--s-7) 0 0;
  max-width: 46rem;
}
.shift-row {
  display: grid;
  grid-template-columns: 8fr 9fr 7fr;
  gap: 3px;
  align-items: center;
}

.shift-labels span,
.shift-times span {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--s-muted);
}
.shift-labels .is-on { color: var(--geo-cyan); }
.shift-labels span:nth-child(2),
.shift-times span:nth-child(2) { text-align: center; }
.shift-times span:last-child { text-align: right; }

.shift-bars span { height: 0.875rem; border-radius: var(--r-1); }
.shift-off { background: rgba(255, 255, 255, 0.1); }
.shift-on {
  background: var(--geo-cyan);
  box-shadow: 0 0 0 1px rgba(110, 231, 255, 0.5), 0 6px 18px -6px rgba(110, 231, 255, 0.5);
}

/* ─── 03 Full-bleed photo band ───────────────────────────────────────────── */
.band-photo {
  position: relative;
  isolation: isolate;
  /* Losing this section's standfirst left the band barely taller than its own padding, which
     crops the photograph to a sliver. The floor gives the picture room without adding words.
     It never bites on a phone, where the stacked claims are taller than this on their own. */
  min-height: 30rem;
  display: grid;
  align-content: center;
  background: var(--ink);

  --s-bg:     var(--ink);
  --s-text:   #F5F7FA;
  --s-text-2: #C3CBD6;
  --s-muted:  #98A2AE;
  --s-rule:   rgba(255, 255, 255, 0.14);
  --s-accent: var(--geo-300);
  --s-em:     var(--geo-300);
  color: var(--s-text-2);
}

.band-photo .band-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 68% 50%;
}

/* The scrim. Copy sits on the left, so the gradient is heaviest there and lets the shop show
   through on the right. Without it the text is unreadable over the shelving. */
.band-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(90deg, rgba(10, 12, 16, 0.97) 0%, rgba(10, 12, 16, 0.93) 42%,
                           rgba(10, 12, 16, 0.74) 72%, rgba(10, 12, 16, 0.58) 100%),
    linear-gradient(180deg, rgba(10, 12, 16, 0.55), rgba(10, 12, 16, 0.35));
}

.band-photo-inner { position: relative; }

/* ─── Verdict chip ───────────────────────────────────────────────────────── */
/* Worn in 01's three cases and on every row of the sheet. Colour comes from the four
   .tier-* classes above, which come from packages/brand. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0.25rem 0.625rem;
  border: 1px solid;
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 500;
  white-space: nowrap;
}

/* ─── 03 The sheet ──────────────────────────────────────────────────────── */
/* The timesheet as the thing itself rather than a table of it: a panel with the total in
   its head, the whole day as one bar at full width, and the visits underneath. The old
   version buried 10px gantt bars inside a table cell and led with a column header. */
.sheet {
  margin: var(--s-8) 0 0;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--sh-3);
  overflow: hidden;
}

.sheet-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3) var(--s-5);
  padding: var(--s-4) var(--s-5);
  background: var(--ink);
  color: #AFB8C4;
}
.sheet-label {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.sheet-total { display: flex; align-items: baseline; gap: var(--s-2); }
/* The number the whole section is about, so it gets to be the size of one. */
.sheet-total strong {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: 700;
  letter-spacing: var(--tr-heading);
  color: #F5F7FA;
}
.sheet-total span {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

/* The day bar. */
.sheet-day {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--rule);
}
.sd-end {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  color: var(--text-muted);
}
.sd-track {
  position: relative;
  flex: 1;
  height: 0.875rem;
  background: var(--paper-3);
  border-radius: var(--r-pill);
}
/* Both ends are real data ends rather than a baseline, so the blocks are fully rounded.
   A 2px surface ring keeps two visits legible if a round ever puts them back to back. */
.sd-visit {
  position: absolute;
  top: 0;
  height: 100%;
  min-width: 0.875rem;
  border-radius: var(--r-pill);
  box-shadow: 0 0 0 2px var(--paper);
}
.sd-visit.is-verified   { background: var(--fp-tier-verified-fg); }
.sd-visit.is-probable   { background: var(--fp-tier-probable-fg); }
.sd-visit.is-unverified { background: var(--fp-tier-unverified-fg); }

/* The four visits. */
.sheet-table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }

.sheet-table th,
.sheet-table td {
  text-align: left;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--rule);
}
.sheet-table th:first-child,
.sheet-table td:first-child { padding-inline-start: var(--s-5); }
.sheet-table th:last-child,
.sheet-table td:last-child { padding-inline-end: var(--s-5); text-align: right; }

.sheet-table thead th {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding-block: var(--s-3);
}
.sheet-table tbody th { color: var(--text); font-weight: 600; white-space: nowrap; }
.sheet-table tbody td { color: var(--text-2); }
.sheet-table tbody tr:last-child th,
.sheet-table tbody tr:last-child td { border-bottom: none; }

.t-col { font-variant-numeric: tabular-nums; white-space: nowrap; }
.num-col { font-variant-numeric: tabular-nums; white-space: nowrap; }

.sheet-foot {
  padding: var(--s-4) var(--s-5);
  background: var(--paper-2);
  border-top: 1px solid var(--rule);
  font-size: var(--t-sm);
  color: var(--text-muted);
}

/* Present for a screen reader, gone for everyone else — the panel's own head says this. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ─── CTA ────────────────────────────────────────────────────────────────── */
.band-cta { position: relative; overflow: hidden; }
.band-cta::before {
  content: '';
  position: absolute;
  inset: 35% -10% -60% -10%;
  background: radial-gradient(closest-side, rgba(31, 95, 168, 0.3), transparent 75%);
  pointer-events: none;
}

.cta-inner {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--s-5);
  text-align: center;
}
.cta-inner h2 { max-width: 26ch; }
.cta-inner .section-lede { max-width: 54ch; }
.cta-inner .cta-row { justify-content: center; margin-top: var(--s-2); }
.cta-meta {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--s-muted);
}

/* ─── Footer ─────────────────────────────────────────────────────────────── */
.site-footer { padding-block: var(--s-7); border-top: 1px solid var(--s-rule); }

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  font-size: var(--t-sm);
}
.footer-brand { display: flex; align-items: center; gap: var(--s-3); }
.footer-brand .wordmark-mark { width: 2rem; height: 2rem; }
.footer-brand p { line-height: 1.35; }
.footer-brand strong { color: var(--s-text); font-family: var(--font-display); font-size: var(--t-md); }

.muted { color: var(--s-muted); }
.footer-note { max-width: 34ch; text-align: right; }
.footer-note a { color: var(--s-text-2); border-bottom: 1px solid var(--s-rule); }
.footer-note a:hover { color: var(--s-accent); border-color: currentColor; }

@media (max-width: 44rem) { .footer-note { text-align: left; max-width: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   Phones and small tablets
   ───────────────────────────────────────────────────────────────────────────
   Everything below was written against renders at 360px and 390px, not guessed.
   The two horizontal-overflow bugs this page had are fixed at their source
   above (.check-grid > * and the min() in .facts) rather than papered over here.

   The theme of this block is that a phone is short, not just narrow. At 360px
   the page ran to about 9,000px — twenty-five screens — and most of that was
   layout that had simply stacked rather than been reconsidered: four tier cards
   with their glyphs above their headings, a definition list wasting a line per
   value, and 64px gaps between every block.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 48rem) {
  /* ── The shift window ──
     "Not recorded" wraps in the outer columns on a phone and makes the label row
     ragged. The dark bars and the 00:00/24:00 ends already say it, so only the
     lit band keeps its label. visibility, not display: the spans have to stay in
     the grid or the three rows stop lining up with each other. */
  .shift-labels span:not(.is-on) { visibility: hidden; }

  /* ── The ring motif ──
     The rings are positioned by their edges, so as the viewport narrows their
     centre — the one part the mask leaves fully opaque — walks inwards. At 360px
     it landed in the middle of the heading and turned a texture into a backdrop.
     Offsetting by half the block's own size pins that centre to the corner, so
     only the faded quadrant reaches the copy. */
  .bg-rings::before {
    top: -26rem;
    right: -26rem;
    opacity: 0.22;
  }

  /* ── Tap targets ──
     The header button came out about 34px tall against a 44px floor. Applied
     from 48rem down, because a tablet is a touch device as much as a phone. */
  .btn-sm { padding: 0.6875rem var(--s-4); }

  /* Gaps between blocks inside a section. 64px reads as generous on a desktop
     and as a dead screen on a phone. */
  .cases,
  .claims,
  .shift,
  .sheet { margin-top: var(--s-6); }

  /* ── The sheet ──
     Shop + the clock range + the widest chip ("Needs approval", a product label
     and not ours to shorten) overruns 320px even with four columns, and it was
     the Answer column that got clipped — the one thing the row exists to say.
     The duration goes instead: the range implies it and the panel head already
     carries the day's total. Measured at 360px, not estimated. */
  .sheet-table { font-size: var(--t-xs); }
  .sheet-table .num-col { display: none; }
  .sheet-table th,
  .sheet-table td { padding: var(--s-2); }
  .sheet-table th:first-child,
  .sheet-table td:first-child { padding-inline-start: var(--s-3); }
  .sheet-table th:last-child,
  .sheet-table td:last-child { padding-inline-end: var(--s-3); }
  .sheet-table .chip { font-size: 0.6875rem; padding-inline: 0.5rem; }
  .sheet-head,
  .sheet-day,
  .sheet-foot { padding-inline: var(--s-4); }
}

@media (max-width: 34rem) {
  /* Sections themselves. 3.5rem top and bottom puts 112px of nothing between
     every band on a 360px screen. A custom property needs a selector — declared
     bare inside the media query it is simply dropped. */
  :root { --section-pad: 2.75rem; }

  /* ── The geofence panel ──
     A 1.27 panel at 360px wide is only 283px tall, which leaves the map
     cramped under its own HUD. Square gives the aerial half again as much
     area. Safe to change because the photograph (object-fit: cover) and the
     overlay (preserveAspectRatio slice) centre-crop to the same box, so they
     stay registered to each other; the geofence is inset far enough from the
     1400×1100 edges to survive the crop. */
  .geo-panel { aspect-ratio: 1 / 1; }

  /* ── Hero stats ──
     Three items in a two-column grid always leaves one orphaned on its own
     row. As label-left / value-right rows they read like a spec sheet and cost
     three lines instead of six. */
  .hero-stats {
    grid-template-columns: 1fr;
    gap: 0;
    margin-top: var(--s-6);
  }
  .hero-stats > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-4);
    padding-block: var(--s-3);
  }
  .hero-stats > div + div { border-top: 1px solid var(--s-rule); }
  .hero-stats dt { flex: none; }
  .hero-stats dd { margin: 0; text-align: right; }

  /* ── The chart ──
     Scrolling was the wrong answer here: the plot is simple enough to read at
     320px if its type stops shrinking with it. Text in an SVG scales with the
     viewBox, so the sizes go up in user units. The long knee annotation is the
     one thing that will not fit — at this size it runs under the "75 m" end
     label — and the prose beside the chart plus the table below both already
     say what it said. */

  /* ── Controls ──
     Full-width buttons: a bigger target, and a stack of two content-width
     pills at different widths looks like a mistake. */
  .cta-row { flex-direction: column; align-items: stretch; }
  .cta-row .btn { width: 100%; }

  /* The status line wraps to two lines, and a flex row leaves its pip stranded
     beside the first of them. */
  .cta-meta { display: block; text-align: center; }
  .cta-meta .pip {
    display: inline-block;
    vertical-align: 0.1em;
    margin-right: var(--s-2);
  }

}


/* ─── Legal pages ─────────────────────────────────────────────────────────── */
/* /privacy and /terms: one column of prose on paper, the same type scale as the rest. */
.legal { max-width: 68ch; }
.legal h1 { max-width: none; }
.legal h2 { font-size: var(--t-lg); max-width: none; margin-top: var(--s-8); }
.legal p, .legal li { color: var(--s-text-2); margin-top: var(--s-3); line-height: 1.6; }
.legal ul { padding-left: 1.25rem; margin-top: var(--s-3); }
.legal li + li { margin-top: var(--s-2); }
.legal a { color: var(--s-text); text-decoration: underline; text-underline-offset: 0.15em; }
.legal strong { color: var(--s-text); }
