/* Self-hosted so the site never waits on another company's server,
   and so no visitor's browser is asked to talk to one. */

@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url(../fonts/lora-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url(../fonts/lora-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(../fonts/plus-jakarta-sans-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(../fonts/plus-jakarta-sans-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ==========================================================================
   The Main Course: marketing site
   1. Tokens, reset, type, layout primitives
   --------------------------------------------------------------------------
   Design notes (why this looks the way it does)

   AUDIENCE. Restaurant owners who do not use a laptop day to day, often
   reading on a phone, often over 50. Three consequences run through the whole
   sheet: nothing is smaller than 15px and body copy is 18px, every pressable
   thing is at least 52px tall, and there is no jargon anywhere in the copy.

   COLOUR. The accent is the platform's own `petrol` ramp, copied verbatim from
   its tailwind.config.ts. It is a custom hue (h207) chosen so it can never be
   mistaken for red/amber/emerald/blue, which mean error/warning/success/info
   inside the product, and so it stays out of the warm half of the wheel that
   belongs to the restaurant's own brand colours. Petrol is used for buttons,
   rules, glyphs, links and one deep band, never as a wash.

   GROUND. Sections alternate between white and one step of warm grey that runs
   off both edges of the screen. That "band" idea is lifted from the platform's
   dashboard, where a change of ground, not a horizontal line, is what
   separates one thing from the next. There are almost no grey lines here.

   MOTION. transform and opacity only, like the product itself. Everything has
   an explicit resting state so `prefers-reduced-motion` can switch the whole
   system off without leaving anything invisible.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */

:root {
  /* The platform's petrol ramp, verbatim. Re-hueing is safe; re-laddering the
     lightness is not: each stop's contrast is a property of the stop. */
  --petrol-50:  #edfafc;
  --petrol-100: #d9f3f7;
  --petrol-200: #b8e7ee;
  --petrol-300: #8fd2db;
  --petrol-400: #5ab5c1;
  --petrol-500: #289aa7;
  --petrol-600: #04818e;
  --petrol-700: #036974;  /* primary button, clears 4.5:1 on white */
  --petrol-800: #04555e;
  --petrol-900: #02444b;
  --petrol-950: #00282d;

  /* Ink and paper. The ink carries a trace of the accent so black never looks
     like a different product bolted on. */
  --ink:        #0b1e22;
  --ink-2:      #33474b;   /* body copy */
  --ink-3:      #5d7175;   /* quiet labels, captions */
  --paper:      #ffffff;
  --paper-warm: #f7f6f3;   /* the band */
  --paper-deep: #f1efea;
  --line:       #e6e3dc;
  --line-soft:  #efedE7;

  /* Semantic, borrowed from the product so a screenshot and this page agree. */
  --good:   #047857;
  --good-bg:#ecfdf5;
  --warn:   #b45309;
  --warn-bg:#fffbeb;

  /* Type */
  --font-display: "Lora", ui-serif, Georgia, "Times New Roman", serif;
  --font-sans: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* A ladder, not a set of guesses. Fluid between a phone and a wide screen. */
  --t-hero:  clamp(2.5rem, 1.5rem + 3.1vw, 3.75rem);
  --t-h2:    clamp(2rem, 1.35rem + 2.3vw, 3.1rem);
  --t-h3:    clamp(1.375rem, 1.15rem + 0.75vw, 1.75rem);
  --t-lead:  clamp(1.1875rem, 1.09rem + 0.42vw, 1.4375rem);
  --t-body:  1.125rem;   /* 18 */
  --t-small: 1rem;       /* 16 */
  --t-micro: 0.9375rem;  /* 15: the floor. Nothing goes under it. */

  /* Space */
  --gut: clamp(1.25rem, 0.6rem + 2.6vw, 2.5rem);
  --measure: 1240px;
  --measure-narrow: 720px;
  --sec-y: clamp(4.5rem, 3rem + 7vw, 8.5rem);

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;
  --r-xl: 32px;

  /* Shadows live on their own layer so hover can animate OPACITY rather than
     the shadow itself, because interpolating box-shadow repaints everything showing
     through the element. */
  --sh-1: 0 1px 2px rgba(11, 30, 34, 0.05), 0 4px 14px rgba(11, 30, 34, 0.05);
  --sh-2: 0 2px 6px rgba(11, 30, 34, 0.06), 0 18px 44px rgba(11, 30, 34, 0.11);
  --sh-3: 0 30px 70px rgba(2, 68, 75, 0.18);

  --ease: cubic-bezier(0.22, 0.68, 0.28, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --spring: cubic-bezier(0.34, 1.4, 0.5, 1);
}

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
  /* Per CSS Overflow 3, `hidden` on one axis computes the other to `auto` and
     silently makes this a scroll container. `clip` is exempt. */
  overflow-x: clip;
}

body {
  margin: 0;
  overflow-x: clip;
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: 1.65;
  color: var(--ink-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
}

/* A whisper of grain. Warms the flat paper without becoming a texture. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.12;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }

a { color: var(--petrol-700); text-decoration-thickness: 1.5px; text-underline-offset: 3px; }
a:hover { color: var(--petrol-600); }

button, input, select, textarea { font: inherit; color: inherit; }

ul, ol { margin: 0; padding: 0; }

hr { border: 0; height: 1px; background: var(--line); margin: 0; }

::selection { background: var(--petrol-200); color: var(--petrol-950); }

:focus-visible {
  outline: 3px solid var(--petrol-600);
  outline-offset: 3px;
  border-radius: 4px;
}
/* Petrol-600 on the dark band's lighter corner is 1.9:1, which is not a focus
   ring, it is a rumour of one. Keyboard users get a white one there. */
.band-dark :focus-visible,
.band-dark.cta-band :focus-visible { outline-color: #fff; }

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

.skip {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -140%);
  z-index: 200;
  background: var(--petrol-700);
  color: #fff;
  padding: 0.85rem 1.5rem;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  text-decoration: none;
  font-weight: 600;
  transition: transform 0.2s var(--ease);
}
.skip:focus-visible { transform: translate(-50%, 0); color: #fff; }

/* --------------------------------------------------------------------------
   Layout primitives
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gut);
  position: relative;
  z-index: 1;
}
.wrap-narrow { max-width: var(--measure-narrow); }

.section { padding-block: var(--sec-y); position: relative; }
.section-tight { padding-block: clamp(3rem, 2rem + 4vw, 5rem); }

/* The band. One step of grey that runs off both edges of the screen: the
   thing that separates one section from the next, instead of a rule. */
.band { background: var(--paper-warm); }
.band-deep { background: var(--paper-deep); }

.band-dark {
  background:
    radial-gradient(120% 130% at 12% 0%, #06525c 0%, rgba(6, 82, 92, 0) 60%),
    radial-gradient(90% 120% at 100% 100%, #056473 0%, rgba(5, 100, 115, 0) 55%),
    var(--petrol-950);
  color: #cfe9ed;
}
.band-dark h2, .band-dark h3, .band-dark h4 { color: #fff; }
/* Links on the dark band go pale petrol, but a BUTTON is not a link: `.band-dark a`
   is one point more specific than `.btn-white`, so without the :not() every white
   pill on a dark band drew its label in #b8e7ee on #fff, which is 1.3:1 and
   effectively invisible. Two of those were the primary call to action. */
.band-dark a:not(.btn) { color: var(--petrol-200); }

/* --------------------------------------------------------------------------
   Type helpers
   -------------------------------------------------------------------------- */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-sans);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--petrol-700);
  margin: 0;
}
.band-dark .eyebrow { color: var(--petrol-300); }

/* The eyebrow used to draw a 26px bar before its text. Inline and immediately
   in front of words, it read as a long dash rather than as a rule, so it is
   gone. inline-flex and the gap stay: they cost nothing with one child and
   keep the label's baseline behaviour identical. */

h1, .t-hero { font-size: var(--t-hero); letter-spacing: -0.03em; line-height: 1.04; }
h2, .t-h2 { font-size: var(--t-h2); letter-spacing: -0.022em; }
h3, .t-h3 { font-size: var(--t-h3); letter-spacing: -0.015em; line-height: 1.25; }

.lead {
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 40ch;
}
.band-dark .lead { color: #bcdde3; }

.small { font-size: var(--t-small); }
.micro { font-size: var(--t-micro); }
.quiet { color: var(--ink-3); }
/* The dark band is a gradient, not a flat colour: it lightens to about #06525c
   in two corners. Every value on it is checked against THAT, not against the
   #00282d underneath, because the corner is where the quiet text actually sits.
   This one was #8fb9c1 and measured 4.2:1 there. */
.band-dark .quiet { color: #a3c9d0; }
.strong-ink { color: var(--ink); font-weight: 600; }

/* An arrow glyph is drawn on the maths axis, about the middle of the LOWERCASE
   x-height. Put one in a line of uppercase and it sits visibly low. This lifts
   it to the optical middle of the caps. */
.arrow-mid { display: inline-block; transform: translateY(-0.08em); }

/* The 2px rule that opens a block. Straight out of the product's own flat
   grammar, where a heavy short rule opens each section instead of a card. */
/* The short bar that sat above every section heading has gone the same way.
   Only the auth pages keep a rule, and theirs runs the full width of the
   column, so it reads as a masthead line and not as a dash. */

.sec-head { max-width: 46rem; margin-bottom: clamp(2.5rem, 1.5rem + 3vw, 4rem); }
.sec-head .lead { margin-top: 1.1rem; max-width: 46ch; }
.sec-head-center { margin-inline: auto; text-align: center; }
.sec-head-center .rule { margin-inline: auto; transform-origin: center; }
.sec-head-center .lead { margin-inline: auto; }

/* --------------------------------------------------------------------------
   Motion system
   --------------------------------------------------------------------------
   One class does the reveal, one variable does the stagger. Everything below
   animates transform/opacity only and has a resting state that is correct
   even if the observer never fires.

   THE HIDDEN HALF IS SCOPED TO `.js`, which an inline script in the head puts
   on <html>. A reveal animation is the one kind of decoration that can hide a
   page permanently: with scripting off, an unscoped `opacity: 0` leaves a
   restaurant owner reading a blank band and no way to know there was anything
   in it. So nothing here starts hidden unless something is definitely going to
   un-hide it.
   -------------------------------------------------------------------------- */

.rise, .rise-l, .rise-r {
  transition:
    opacity 0.7s var(--ease-out) calc(var(--d, 0) * 85ms),
    transform 0.9s var(--ease-out) calc(var(--d, 0) * 85ms);
}
.rise-scale {
  transition:
    opacity 0.8s var(--ease-out) calc(var(--d, 0) * 85ms),
    transform 1s var(--ease-out) calc(var(--d, 0) * 85ms);
}

/* `will-change` only while the element is still waiting. Left on permanently
   it holds a compositing layer per element for the life of the page. */
.js .rise:not(.in), .js .rise-l:not(.in), .js .rise-r:not(.in), .js .rise-scale:not(.in) {
  will-change: transform, opacity;
}

.js .rise { opacity: 0; transform: translate3d(0, 26px, 0); }
.js .rise-l { opacity: 0; transform: translate3d(-30px, 0, 0); }
.js .rise-r { opacity: 0; transform: translate3d(30px, 0, 0); }
.js .rise-scale { opacity: 0; transform: scale(0.955) translate3d(0, 18px, 0); }

.rise.in, .rise-l.in, .rise-r.in, .rise-scale.in { opacity: 1; transform: none; }

/* The rule draws itself in. */
.rule-draw { transition: transform 0.75s var(--ease-out) calc(var(--d, 0) * 85ms); }
.js .rule-draw { transform: scaleX(0); }
.rule-draw.in { transform: scaleX(1); }

/* Words that arrive line by line. Each line is its own overflow window, so the
   text rises out of nothing rather than fading through the paper. */
.lines { display: block; }
.lines .ln { display: block; overflow: hidden; padding-bottom: 0.06em; }
.lines .ln > span {
  display: block;
  transition: transform 1s var(--ease-out) calc(var(--d, 0) * 110ms);
}
.js .lines .ln > span { transform: translate3d(0, 105%, 0); }
.lines.in .ln > span { transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  /* Anything whose visible state is PRODUCED by its motion needs an explicit
     resting state, not just `animation: none`. */
  .rise, .rise-l, .rise-r, .rise-scale { opacity: 1 !important; transform: none !important; }
  .rule-draw { transform: scaleX(1) !important; }
  .lines .ln > span { transform: none !important; }
  .breathe, .sheen { animation: none !important; }
  .ds-box svg { transform: scale(1) !important; }
  .ds-row { opacity: 1 !important; }
  .meter-fill { transform: scaleX(var(--f, 0.6)) !important; }
}
/* ==========================================================================
   2. Components
   ========================================================================== */

/* --------------------------------------------------------------------------
   Buttons, big enough for a thumb on a phone in a busy kitchen.
   -------------------------------------------------------------------------- */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 56px;
  padding: 0.9rem 1.6rem;
  border: 0;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.22s var(--spring), color 0.2s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(0.985); }

.btn-primary { background: var(--petrol-700); color: #fff; }
.btn-primary:hover { color: #fff; }
/* Depth as a separate layer, so hover animates opacity and never repaints a
   shadow through everything behind it. */
.btn-primary::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow: 0 10px 26px rgba(3, 105, 116, 0.38);
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
.btn-primary:hover::before { opacity: 1; }
/* A slow sheen travelling across the primary call to action. */
.btn-primary::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,0.28) 50%, transparent 70%);
  transform: translateX(-120%);
}
.btn-primary:hover::after { animation: sheen 0.9s var(--ease-out); }
@keyframes sheen { to { transform: translateX(120%); } }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--line);
}
.btn-ghost:hover { color: var(--petrol-800); box-shadow: inset 0 0 0 2px var(--petrol-300); }

.btn-soft { background: var(--petrol-50); color: var(--petrol-800); box-shadow: inset 0 0 0 1px var(--petrol-200); }
.btn-soft:hover { color: var(--petrol-900); background: var(--petrol-100); }

.btn-white, .btn-white:hover, .band-dark .btn-white { background: #fff; color: var(--petrol-900); }

.btn-on-dark, .btn-on-dark:hover, .band-dark .btn-on-dark { background: transparent; color: #fff; }
.btn-on-dark { box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.34); }
.btn-on-dark:hover { box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.7); }

.btn-lg { min-height: 64px; padding: 1rem 2.1rem; font-size: 1.1875rem; }
.btn-block { width: 100%; }

.btn .arw { transition: transform 0.3s var(--ease-out); }
.btn:hover .arw { transform: translateX(4px); }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.9rem; align-items: center; }

/* A plain text link that behaves like a button target. */
.tlink {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 700;
  color: var(--petrol-700);
  text-decoration: none;
  min-height: 44px;
}
.tlink::after { content: "→"; transition: transform 0.3s var(--ease-out); }
.tlink:hover::after { transform: translateX(5px); }

/* --------------------------------------------------------------------------
   Chips and small marks
   -------------------------------------------------------------------------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  background: var(--petrol-50);
  color: var(--petrol-800);
  box-shadow: inset 0 0 0 1px var(--petrol-200);
  font-size: var(--t-micro);
  font-weight: 700;
  white-space: nowrap;
}
.chip-plain { background: #fff; color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--line); }
.chip-good { background: var(--good-bg); color: var(--good); box-shadow: inset 0 0 0 1px #a7f3d0; }
.chip-warn { background: var(--warn-bg); color: var(--warn); box-shadow: inset 0 0 0 1px #fde68a; }
.band-dark .chip { background: rgba(255,255,255,0.08); color: #d5eef2; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.16); }

.tick {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: var(--petrol-50);
  color: var(--petrol-700);
  display: grid;
  place-items: center;
  box-shadow: inset 0 0 0 1px var(--petrol-200);
}
.tick svg { width: 14px; height: 14px; }
.band-dark .tick { background: rgba(255,255,255,0.1); color: var(--petrol-200); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18); }

.cross { background: #fff; color: #a8b4b6; box-shadow: inset 0 0 0 1px var(--line); }

/* Checklists */
.checks { list-style: none; display: grid; gap: 0.85rem; }
.checks li { display: flex; gap: 0.8rem; align-items: flex-start; }
.checks li > span:last-child { padding-top: 0.1rem; }

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */

.card {
  position: relative;
  background: #fff;
  border-radius: var(--r-lg);
  box-shadow: inset 0 0 0 1px var(--line);
  padding: clamp(1.5rem, 1rem + 1.6vw, 2.25rem);
  transition: transform 0.35s var(--ease-out);
  isolation: isolate;
}
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow: var(--sh-2);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
}
.card-hover:hover { transform: translateY(-5px); }
.card-hover:hover::before { opacity: 1; }

.card h3 { margin-bottom: 0.65rem; }
.card p { color: var(--ink-2); }

.icon-badge {
  width: 52px;
  height: 52px;
  border-radius: 15px;
  display: grid;
  place-items: center;
  background: linear-gradient(160deg, var(--petrol-50), var(--petrol-100));
  color: var(--petrol-700);
  box-shadow: inset 0 0 0 1px var(--petrol-200);
  margin-bottom: 1.1rem;
}
.icon-badge svg { width: 24px; height: 24px; }

/* --------------------------------------------------------------------------
   Top bar
   -------------------------------------------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(1.5) blur(14px);
  -webkit-backdrop-filter: saturate(1.5) blur(14px);
  transition: box-shadow 0.3s var(--ease), background 0.3s var(--ease);
}
.topbar::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--line);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
}
.topbar.stuck::after { opacity: 1; }

.topbar-in {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  min-height: 76px;
}

.brand { display: inline-flex; align-items: center; gap: 0.85rem; text-decoration: none; margin-right: auto; }
.brand:hover { color: inherit; }

/* The platform's own logo artwork, the same file the application's log-in screen
   renders. It replaced a placeholder: a petrol tile holding a stroked cloche,
   beside the product's name set in the display face.

   TWO THINGS WENT WITH IT and both were consequences rather than choices. The
   name is INSIDE the artwork, so `.brand-name` had nothing left to draw and is
   gone; and the tile's `rotate(-8deg) scale(1.06)` hover went too, because
   tilting a finished lockup that contains type reads as a rendering fault rather
   than as a flourish. Nothing here animates now, which also means the brand block
   is the one part of the bar with no motion budget spent on it.

   The file's ground is REMOVED (the application repo's
   scripts/brand/transparent-logo.mjs). It has to be: `--paper-warm` is #f7f6f3
   rather than #ffffff, so a white-backed raster in the footer is a faintly
   visible rectangle, and `.topbar` is rgba(255,255,255,0.82) over a backdrop
   blur, so page content scrolls underneath it — over this site's own dark band
   the bar composites to about #d1d3d3 while a white patch inside it stays #fff,
   which reads as a bright box sliding across the logo. */
.brand-logo {
  height: 40px;
  width: auto;
  flex: none;
}

/* The positioning line, which used to sit under the product's name inside
   `.brand-name` and now stands beside the lockup. It is deliberately KEPT rather
   than dropped with the wordmark it hung off: it is copy about the business, not
   part of the mark.

   It carries a rule on its left because without one two pieces of type sit side
   by side with nothing saying which is the name and which is the description. */
.brand-tag {
  padding-left: 0.85rem;
  border-left: 1px solid var(--line);
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  line-height: 1.25;
  text-transform: uppercase;
  color: var(--petrol-600);
  /* Measured rather than guessed: 11em sets it as WEBSITES FOR / RESTAURANTS.
     7.5em broke it over three lines, which is 49px of type inside a 68px bar and
     reads as text that did not fit rather than as a descriptor. */
  max-width: 11em;
}

.nav { display: flex; align-items: center; gap: 0.35rem; }
.nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.7rem;
  border-radius: 10px;
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--ink-2);
  text-decoration: none;
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0.7rem; right: 0.7rem; bottom: 8px;
  height: 2px;
  border-radius: 2px;
  background: var(--petrol-600);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--ease-out);
}
.nav a:hover { color: var(--ink); }
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--ink); }

.topbar-cta { display: flex; align-items: center; gap: 0.6rem; }
.topbar-cta .btn { min-height: 48px; padding: 0.65rem 1.3rem; font-size: var(--t-small); }

.burger {
  display: none;
  width: 52px; height: 52px;
  border: 0;
  border-radius: 12px;
  background: var(--paper-warm);
  box-shadow: inset 0 0 0 1px var(--line);
  cursor: pointer;
  place-items: center;
}
.burger span {
  display: block;
  width: 20px; height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}
.burger span + span { margin-top: 5px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 76px 0 0;
  z-index: 99;
  background: #fff;
  padding: 1.5rem var(--gut) 3rem;
  overflow-y: auto;
  opacity: 0;
  transform: translateY(-12px);
  pointer-events: none;
  transition: opacity 0.28s var(--ease), transform 0.35s var(--ease-out);
}
.mobile-nav.open { opacity: 1; transform: none; pointer-events: auto; }
.mobile-nav a.mnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 64px;
  padding: 0 0.25rem;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--line-soft);
}
.mobile-nav a.mnav::after { content: "→"; color: var(--petrol-600); }
.mobile-nav .btn-row { margin-top: 2rem; flex-direction: column; align-items: stretch; }

body.nav-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   Image placeholders
   --------------------------------------------------------------------------
   Real photography is coming later. Until then every picture is a drawn panel
   that states what belongs there, so the layout is honest at every size rather
   than collapsing around a missing file.
   -------------------------------------------------------------------------- */

.ph {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--r-md);
  background:
    linear-gradient(135deg, var(--petrol-50) 0%, #f3f7f8 55%, var(--petrol-100) 100%);
  box-shadow: inset 0 0 0 1px rgba(4, 129, 142, 0.16);
  color: var(--petrol-700);
  min-height: 120px;
  isolation: isolate;
}
.ph::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: repeating-linear-gradient(
    -45deg,
    rgba(4, 129, 142, 0.055) 0 2px,
    transparent 2px 11px
  );
}
.ph-in { display: grid; justify-items: center; gap: 0.5rem; padding: 1rem; text-align: center; }
.ph-in svg { width: 30px; height: 30px; opacity: 0.7; }
/* No opacity on either of these. A placeholder caption is still text somebody
   has to read, and 0.7 of petrol-600 on a pale tint is 2.8:1. */
.ph-label {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--petrol-800);
}
.ph-note { font-size: var(--t-micro); color: var(--petrol-700); }

/* --------------------------------------------------------------------------
   Forms (log in / sign up, and anywhere else)
   -------------------------------------------------------------------------- */

.field { display: block; margin-bottom: 1.35rem; }
.field > label {
  display: block;
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 0.45rem;
}
.field .hint { display: block; font-size: var(--t-micro); color: var(--ink-3); margin-top: 0.4rem; }

.input {
  width: 100%;
  min-height: 58px;
  padding: 0.9rem 1.05rem;
  border: 0;
  border-radius: 12px;
  background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--line);
  font-size: 1.0625rem;
  color: var(--ink);
  transition: box-shadow 0.2s var(--ease), transform 0.2s var(--ease);
}
/* A placeholder is still something a person has to read before they can type
   over it. #9aa8aa was 2.5:1 on white; this is 4.6:1 and still clearly lighter
   than the value they enter. */
.input::placeholder { color: #67797c; opacity: 1; }
.input:hover { box-shadow: inset 0 0 0 1.5px #d4d0c8; }
.input:focus {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--petrol-600), 0 0 0 4px var(--petrol-100);
}
.input[aria-invalid="true"] { box-shadow: inset 0 0 0 2px #dc2626; }

.err {
  display: none;
  margin-top: 0.45rem;
  font-size: var(--t-micro);
  font-weight: 600;
  color: #b91c1c;
}
.err.on { display: block; }

/* --------------------------------------------------------------------------
   The two legal documents (privacy.html, terms.html).

   Those pages are GENERATED from the product's single copy of the text —
   scripts/legal/build-marketing-pages.ts — so nothing about them is
   hand-written except the rules below. They borrow this site's own head, top
   bar and footer from faq.html at generation time, so only the document itself
   needs dressing.

   `.wrap-narrow` (720px) already sets the measure; this adds the vertical
   rhythm a long numbered document needs and a table that scrolls in its own box
   rather than widening the page.
   -------------------------------------------------------------------------- */

/* NOT `--t-hero` (up to 60px), which every other h1 on this site takes: a
   document is read rather than announced, and this is the product's own legal
   heading transcribed, so the two renderings open at the same size. */
.legal h1 {
  font-size: clamp(1.9rem, 1.5rem + 1.4vw, 2.35rem);
  letter-spacing: -0.015em;
  line-height: 1.12;
}
.legal .legal-standfirst {
  margin-top: 0.6rem;
  font-size: var(--t-body);
  color: var(--ink-3);
}
.legal .legal-meta { margin-top: 1.25rem; }

/* One 2px rule opening the document, the same weight the product's own page
   uses under its title. Nothing else on these pages is a line. */
.legal .legal-body {
  margin-top: 2rem;
  padding-top: 2rem;
  border-top: 2px solid #d4d0c8;
  color: var(--ink-2);
}

.legal .legal-body h2 {
  font-size: var(--t-h3);
  letter-spacing: -0.015em;
  margin-top: 2.75rem;
  scroll-margin-top: 5rem;   /* the top bar is sticky; a #section link must clear it */
}
.legal .legal-body h2:first-child { margin-top: 0; }

.legal .legal-body p { margin-top: 1rem; line-height: 1.65; }
.legal .legal-body ul {
  margin-top: 1rem;
  padding-left: 1.35rem;
  list-style: disc;
  line-height: 1.65;
}
.legal .legal-body li { margin-top: 0.6rem; }
.legal .legal-body strong { color: var(--ink); font-weight: 700; }

.legal .legal-table { margin-top: 1.5rem; overflow-x: auto; }
.legal .legal-table table {
  width: 100%;
  min-width: 38rem;
  border-collapse: collapse;
  text-align: left;
}
.legal .legal-table th {
  padding: 0 1.25rem 0.5rem 0;
  vertical-align: bottom;
  border-bottom: 2px solid #d4d0c8;
  font-size: var(--t-micro);
  font-weight: 700;
  color: var(--ink);
}
.legal .legal-table td {
  padding: 0.75rem 1.25rem 0.75rem 0;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-micro);
  line-height: 1.55;
}

/* --------------------------------------------------------------------------
   The agreements on the sign-up screen: one tick box per document.

   The product carries the same two (`app/_components/auth-chrome.ts` →
   AUTH_CHECKBOX), and this is the pair kept in step with it — the log-in and
   sign-up screens here are the reference the product's were ported from, and
   the whole point of that reference is that it does not quietly fall behind.

   The box is `.input`'s own geometry brought down to 22px: the same 1.5px inset
   hairline instead of a border, the same doubled focus ring, the same error
   edge. `appearance: none` is what makes the radius and the hairline available
   at all and it takes the browser's tick with it, so the glyph is a background
   image — lucide's `check`, inline, because a published page that fetches an
   icon from somewhere else is a page that can lose it.
   -------------------------------------------------------------------------- */

.agree { display: flex; align-items: flex-start; gap: 0.75rem; }
/* `* +` rather than `.agree +`: the message for the row above sits between the
   two, so an adjacent-sibling rule naming both rows matches neither once one of
   them is wrong — which is the only time anybody looks. */
.agree-group > * + .agree { margin-top: 0.75rem; }
.agree-group { margin-bottom: 1.35rem; }

.agree input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin: 0.15rem 0 0;
  border: 0;
  border-radius: 7px;
  background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--line);
  transition: box-shadow 0.2s var(--ease);
  cursor: pointer;
}
.agree input[type="checkbox"]:hover { box-shadow: inset 0 0 0 1.5px #d4d0c8; }
.agree input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--petrol-600), 0 0 0 4px var(--petrol-100);
}
.agree input[type="checkbox"][aria-invalid="true"] { box-shadow: inset 0 0 0 2px #dc2626; }
.agree input[type="checkbox"]:checked {
  background-color: var(--petrol-700);
  box-shadow: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 14px 14px;
}

/* A sentence to read, not a name for a box — so the body ink at the form's own
   size rather than `.field > label`'s bold, with the document's title inside it
   carrying the emphasis as a link. The words are part of the target. */
.agree > label {
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--ink-2);
  cursor: pointer;
}

/* On the sentence's own left edge (22px box + the 0.75rem gap) — under the box
   instead, the message reads as belonging to the row above it. */
.agree-err { margin-left: calc(22px + 0.75rem); }

.pw-wrap { position: relative; }
.pw-toggle {
  position: absolute;
  right: 6px; top: 50%;
  transform: translateY(-50%);
  min-height: 46px;
  padding: 0 0.9rem;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--petrol-700);
  font-size: var(--t-micro);
  font-weight: 700;
  cursor: pointer;
}
.pw-toggle:hover { background: var(--petrol-50); }

.form-note {
  margin-top: 1.5rem;
  padding: 0.9rem 1.05rem;
  border-radius: 12px;
  background: var(--paper-warm);
  font-size: var(--t-micro);
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   Accordion (questions)
   -------------------------------------------------------------------------- */

.acc { border-top: 1px solid var(--line); }
.acc-item { border-bottom: 1px solid var(--line); }
.acc-btn {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  min-height: 76px;
  padding: 1.1rem 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.3125rem);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.012em;
}
.acc-btn:hover { color: var(--petrol-700); }
.acc-sign {
  margin-left: auto;
  flex: none;
  width: 34px; height: 34px;
  border-radius: 999px;
  background: var(--petrol-50);
  box-shadow: inset 0 0 0 1px var(--petrol-200);
  display: grid;
  place-items: center;
  position: relative;
  transition: transform 0.4s var(--spring), background 0.3s var(--ease);
}
.acc-sign::before, .acc-sign::after {
  content: "";
  position: absolute;
  background: var(--petrol-700);
  border-radius: 2px;
  transition: transform 0.35s var(--ease-out), opacity 0.25s var(--ease);
}
.acc-sign::before { width: 13px; height: 2px; }
.acc-sign::after { width: 2px; height: 13px; }
.acc-btn[aria-expanded="true"] .acc-sign { transform: rotate(180deg); background: var(--petrol-700); }
.acc-btn[aria-expanded="true"] .acc-sign::before { background: #fff; }
.acc-btn[aria-expanded="true"] .acc-sign::after { transform: scaleY(0); opacity: 0; }

.acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s var(--ease-out);
}
.acc-panel > div { overflow: hidden; }
.acc-item.open .acc-panel { grid-template-rows: 1fr; }
.acc-panel p { padding-bottom: 1.6rem; max-width: 62ch; }
.acc-panel p + p { padding-top: 0; margin-top: -0.8rem; }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.footer { background: var(--paper-warm); padding-block: clamp(3.5rem, 2rem + 5vw, 5.5rem) 2.5rem; }
.footer-grid {
  display: grid;
  gap: clamp(2rem, 1rem + 3vw, 3.5rem);
  grid-template-columns: minmax(240px, 1.4fr) repeat(3, minmax(140px, 1fr));
}
.footer .foot-h {
  font-family: var(--font-sans);
  font-size: var(--t-micro);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1rem;
}
.footer ul { list-style: none; display: grid; gap: 0.15rem; }
.footer ul a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  color: var(--ink-2);
  text-decoration: none;
  font-size: var(--t-small);
  font-weight: 500;
}
.footer ul a:hover { color: var(--petrol-700); }
.footer-base {
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  font-size: var(--t-micro);
  color: var(--ink-3);
}
/* ==========================================================================
   3. Sections, product mock-ups, signature motion
   ========================================================================== */

/* --------------------------------------------------------------------------
   Grid utilities
   -------------------------------------------------------------------------- */

.grid-2 { display: grid; gap: clamp(1.25rem, 0.8rem + 1.6vw, 2rem); grid-template-columns: repeat(2, 1fr); }
.grid-3 { display: grid; gap: clamp(1.25rem, 0.8rem + 1.6vw, 2rem); grid-template-columns: repeat(3, 1fr); }
.grid-4 { display: grid; gap: clamp(1rem, 0.6rem + 1.4vw, 1.75rem); grid-template-columns: repeat(4, 1fr); }

.split {
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 5vw, 5rem);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
}
.split-wide { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1.25fr); }
.split-lead { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  padding-block: clamp(2.5rem, 1.5rem + 3.5vw, 4.5rem) clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
  overflow: clip;
}

/* Two very large, very soft petrol clouds drifting behind everything. Blur is
   painted once; only transform animates. */
.hero-glow { position: absolute; inset: -20% -10% auto; height: 130%; z-index: 0; pointer-events: none; }
.hero-glow i {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.5;
}
.hero-glow i:nth-child(1) {
  width: 46vw; height: 46vw; min-width: 380px; min-height: 380px;
  left: -8vw; top: 4vw;
  background: radial-gradient(circle, rgba(90, 181, 193, 0.55), rgba(90, 181, 193, 0) 70%);
  animation: drift1 26s var(--ease) infinite alternate;
}
.hero-glow i:nth-child(2) {
  width: 40vw; height: 40vw; min-width: 320px; min-height: 320px;
  right: -6vw; top: -6vw;
  background: radial-gradient(circle, rgba(184, 231, 238, 0.75), rgba(184, 231, 238, 0) 70%);
  animation: drift2 32s var(--ease) infinite alternate;
}
.hero-glow i:nth-child(3) {
  width: 30vw; height: 30vw; min-width: 260px; min-height: 260px;
  right: 18vw; bottom: 2vw;
  background: radial-gradient(circle, rgba(237, 250, 252, 0.9), rgba(237, 250, 252, 0) 70%);
  animation: drift1 22s var(--ease) infinite alternate-reverse;
}
@keyframes drift1 { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(6%, 5%, 0) scale(1.12); } }
@keyframes drift2 { from { transform: translate3d(0,0,0) scale(1.06); } to { transform: translate3d(-7%, 4%, 0) scale(1); } }

.hero-grid {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 3vw, 3.75rem);
  /* The picture side takes the larger share now that it holds a real
     screenshot. A desktop capture is wide, and starving it of width is what
     makes it read as a thumbnail rather than as a website.

     The words column is measured from the headline rather than taken as a
     share of the row, which is what let the picture grow. `--t-hero` tops out
     at 3.75rem and the longest of the three hand-split lines, "built in
     under", measures 6.13× its font size in Lora, 368px at the 60px it
     resolves to on a default root. 28.5rem (456px) holds it with air to
     spare, and holds it whatever the reader's own font size is, since both
     halves of that sum are rem. Everything left over goes to the picture.

     MEASURE ANY NEW HEADLINE. The previous wording, "We'll do the rest.",
     ran to 442px of the 456 and set this number; the one after it went to
     461px on its first line and 513px on its third, and both silently took a
     second row inside their own clipped window. 452px is the real ceiling.

     A share (the `1fr : 1.18fr` this replaced) does the opposite: it hands the
     headline whatever is left after the picture, so the picture could only be
     enlarged until a hand-split line quietly took a fourth row — quietly
     because nothing overflows and nothing errors, the headline just stops
     being the shape it was written as.

     Read this together with the `.stage` bleed below: the two are one
     decision, and neither on its own is the 30%. */
  grid-template-columns: minmax(0, 28.5rem) minmax(0, 1fr);
  /* Column gap only. The `gap` above still sets the ROW gap, which is what
     separates the words from the picture once this becomes one column. */
  column-gap: clamp(2rem, 1rem + 1.6vw, 2.5rem);
  align-items: center;
}

.hero h1 { margin-block: 1.4rem 1.6rem; }
.hero h1 em { font-style: normal; color: var(--petrol-700); }
.hero .lead { max-width: 34ch; }
.hero .btn-row { margin-top: 2.2rem; }
/* Only the bookings page puts buttons in a page head, and without this they
   sit straight under the standfirst with nothing between them. */
.page-head .btn-row { margin-top: 2rem; }

.hero-assur {
  margin-top: 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  list-style: none;
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--ink-3);
}
/* Four assurances in a narrower column wrapped 1-2-1, which looks like an
   accident. Two tidy columns instead. */
@media (min-width: 1081px) {
  .hero-assur { display: grid; grid-template-columns: repeat(2, max-content); gap: 0.65rem 1.75rem; }
}
.hero-assur li { display: flex; align-items: center; gap: 0.5rem; }
.hero-assur li::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 999px;
  background: var(--petrol-500);
  flex: none;
}

/* --------------------------------------------------------------------------
   Browser frame + the site that builds itself
   -------------------------------------------------------------------------- */

.stage { position: relative; }

/* The rest of the picture's extra 30%: the window's own right-hand margin.
   Past `--measure` the page is empty on a wide screen, and that emptiness is
   worth more to a photograph of a restaurant than it is to nothing. Only the
   RIGHT edge moves — the words column still starts on the same vertical as
   every section below it, which is the alignment the whole page is built on,
   and widening the wrap instead would have shifted the headline left of it.

   Three things bound it. The cap (7rem) is what the words column still owed
   after giving what it could, so the picture arrives at 30% bigger and then
   stops rather than growing across a 27-inch screen. The `- 1rem` is for the
   classic scrollbar `100vw` counts and the viewport does not, and it doubles
   as somewhere for the card that overhangs the picture's right edge to sit.
   And `.hero`'s `overflow: clip` is the backstop: whatever this gets wrong
   can crop the picture but can never put a scrollbar across the page.

   What that adds up to, measured: the full 30% from about 1520px of window
   upwards (776px of picture against the 595px it was), and the same 30% again
   below 1080px where the layout is one column and the picture has the room to
   itself. Between the two it takes what the window has — 26% at 1440, 20% at
   1366, 13% at 1280 — because a two-column hero at those widths has no spare
   room that is not the headline's. */
@media (min-width: 1081px) {
  .stage { margin-right: calc(-1 * clamp(0px, (100vw - var(--measure)) / 2 - 1rem, 7rem)); }
}

.frame {
  position: relative;
  background: #fff;
  border-radius: 20px;
  box-shadow: inset 0 0 0 1px var(--line), var(--sh-2);
  overflow: hidden;
  transform: perspective(1600px) rotateY(-6deg) rotateX(2deg);
  transition: transform 0.9s var(--ease-out);
}
.frame-flat { transform: none; }
.stage:hover .frame { transform: perspective(1600px) rotateY(-2deg) rotateX(0deg); }

.frame-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 0.9rem;
  background: var(--paper-warm);
  border-bottom: 1px solid var(--line);
}
.frame-dots { display: flex; gap: 6px; }
.frame-dots i { width: 10px; height: 10px; border-radius: 999px; background: #d8d5cd; display: block; }
.frame-url {
  flex: 1;
  min-width: 0;
  margin-left: 0.4rem;
  height: 28px;
  border-radius: 999px;
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--line);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0 0.75rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-3);
  overflow: hidden;
  white-space: nowrap;
}
.frame-url svg { width: 12px; height: 12px; flex: none; color: var(--good); }


/* .ph-hero lived here. The hero holds a real screenshot now, so the last
   thing using it is gone and so is it. .ph itself stays: the features page
   still has two placeholders waiting for artwork. */


/* ---------------------------------------------------------------------------
   THE HERO PICTURE, AND THE CARDS AROUND IT

   The picture is a real restaurant built with the product, shown inside the
   same browser frame the rest of the site uses. Three cards float around it,
   each naming a job rather than describing one.

   The composition problem worth knowing about: a desktop screenshot is wide
   and short, while a column of headline, standfirst, buttons and assurances is
   tall. Centre one beside the other and a hole opens up next to the picture.
   The cards are what fills it, which is why they sit high and low rather than
   clustered around the middle.
   --------------------------------------------------------------------------- */

/* .stage:hover .frame straightens a tilted frame. It out-specifies .frame-flat,
   so without this a flat frame would tilt INTO an angle on hover, which is the
   exact opposite of what that rule is for. */
.stage:hover .frame-flat { transform: none; }

.hero-shot { position: relative; z-index: 1; }
.hero-shot .frame { border-radius: 18px; }
.hero-shot img { display: block; width: 100%; height: auto; }

/* A slimmer bar than the one on the features page. That frame holds a drawn
   panel at nearly full width; this one holds a photograph in a narrower
   column, and the chrome has to stay in proportion to it. */
.hero-shot .frame-bar { padding: 0.45rem 0.65rem; }
.hero-shot .frame-dots { gap: 5px; }
.hero-shot .frame-dots i { width: 8px; height: 8px; }
.hero-shot .frame-url { height: 24px; }
/* An empty white pill looks like a text box that failed to load. A muted
   stripe reads as "an address goes here", which is the truth until there is
   one to show. */
.frame-url-ph { display: block; flex: 1; max-width: 160px; height: 7px; border-radius: 4px; background: var(--line); }

.hero-card {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  width: max-content;
  max-width: 14rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 13px;
  padding: 0.55rem 0.75rem;
  /* Lighter than the cards on a pale mock. Over a candlelit room these
     separate on their own and a heavy shadow just looks pasted on. */
  box-shadow: 0 18px 38px -22px rgba(3, 42, 48, 0.45), 0 2px 8px -4px rgba(3, 42, 48, 0.12);
}
.hero-card .ic {
  width: 26px; height: 26px; flex: none;
  border-radius: 8px;
  display: grid; place-items: center;
  background: var(--petrol-50);
  color: var(--petrol-700);
}
.hero-card .ic svg { width: 15px; height: 15px; }
.hero-card b { display: block; font-size: var(--t-micro); line-height: 1.3; }
.hero-card small { display: block; font-size: 0.8125rem; color: var(--ink-3); line-height: 1.4; }

/* Two hang left into the gap between the columns, where the headline has
   already run out of words. The third sits just above the booking bubble in
   the picture, because a card naming the bubble has to point at it. None of
   the three covers the restaurant's own name, its nav or its buttons. */
/* Offsets in rem, not per cent. A percentage offset is a share of the picture,
   so the cards slide further across it as the window narrows and end up on the
   restaurant's name. A fixed offset keeps the same overlap at every width.

   They are arranged around the picture rather than beside it. Hanging them
   into the gap on the left looked right until you measure it: the headline
   and the second button reach further across that column than they appear to,
   and the cards landed on both. Above, below and to the right is the only air
   there actually is, and using it fills the space a wide short picture leaves
   next to a tall column of text. */
.hero-c1 { top: -24%; left: 3.5rem; }
/* It used to hang a rem to the LEFT of the picture, and a bigger picture is
   what took that rem away. `bottom` is a share of the picture's height, so
   growing the picture pushes this card further down — far enough to reach the
   row the assurances sit on. And that row is wider than the column it is in:
   two columns of `max-content` need 515px where the words column is 456, so
   the last assurance has always run a little way into the gap (it did before
   this card was in reach of it, at the narrow end of the two-column layout).
   Nothing sees that overflow because the gap is empty — but this card was
   about to, and a card sitting on the words is the one thing the arrangement
   above is written to avoid. It clears the longest assurance at every width
   the two columns are used at. */
.hero-c2 { bottom: -19%; left: 2.5rem; }
.hero-c3 { bottom: 18%; right: -2rem; }

@media (max-width: 1080px) {
  /* One column now, and the stage is centred. Floating cards over a picture
     this narrow would cover it, so they become a plain row underneath. */
  /* Three across rather than auto-fit, which left the third card sitting on a
     row of its own looking like an afterthought. */
  .hero-cards {
    display: grid;
    gap: 0.7rem;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin-top: 1.6rem;
  }
  .hero-card { position: static; max-width: none; width: auto; }
}

/* Below this three abreast is too narrow to read, so they stack. */
@media (max-width: 720px) {
  .hero-cards { grid-template-columns: minmax(0, 1fr); }
}

/* On a phone the whole desktop capture scaled to 380px turns the restaurant's
   name into a smudge, which throws away the only job the picture has. The
   frame crops into the part that carries the meaning instead of shrinking all
   of it: the name, the standfirst and the two buttons, at a readable size. */
@media (max-width: 640px) {
  .hero-shot img {
    aspect-ratio: 5 / 4;
    object-fit: cover;
    object-position: 26% 62%;
  }
}

/* A live dot, on the bookings counter. */
/* Only ever used on the dark band. --good (#047857) reads as a black dot there
   at 1.6:1; this is the same green lifted for a dark ground. */
.dot-live { width: 9px; height: 9px; border-radius: 999px; background: #34d399; flex: none; position: relative; }
.dot-live::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 999px;
  background: #34d399;
  opacity: 0.28;
  animation: pulse 2.4s var(--ease) infinite;
}
@keyframes pulse { 0% { transform: scale(0.6); opacity: 0.35; } 70%, 100% { transform: scale(1.5); opacity: 0; } }

/* --------------------------------------------------------------------------
   Reassurance strip
   -------------------------------------------------------------------------- */

.assur-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line); border-radius: var(--r-md); overflow: hidden; box-shadow: inset 0 0 0 1px var(--line); }
.assur-strip > div { background: #fff; padding: clamp(1.25rem, 0.9rem + 1vw, 1.75rem); }
.assur-strip svg { width: 24px; height: 24px; color: var(--petrol-600); margin-bottom: 0.75rem; }
.assur-strip b { display: block; color: var(--ink); font-size: 1.0625rem; margin-bottom: 0.3rem; }
.assur-strip p { font-size: var(--t-small); color: var(--ink-3); }

/* --------------------------------------------------------------------------
   Steps: a line that fills as you read down it
   --------------------------------------------------------------------------
   On a wide screen the heading holds the left column and stays put while the
   steps travel past it, so the reader never loses what they are reading a
   list OF. Below 960 it stacks and the heading goes back to being a heading.
   -------------------------------------------------------------------------- */

.how-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(2rem, 1rem + 4vw, 4.5rem);
  align-items: start;
}
.how-grid > .sec-head { position: sticky; top: 118px; margin-bottom: 0; max-width: 30rem; }
@media (max-width: 960px) {
  .how-grid { grid-template-columns: minmax(0, 1fr); }
  .how-grid > .sec-head { position: static; margin-bottom: clamp(2.5rem, 1.5rem + 3vw, 4rem); max-width: 46rem; }
}

.steps { position: relative; display: grid; gap: clamp(2rem, 1rem + 3vw, 3.25rem); padding-left: clamp(3rem, 2rem + 2vw, 4.5rem); }
.steps-track {
  position: absolute;
  left: clamp(1.15rem, 0.75rem + 0.9vw, 1.75rem);
  top: 12px;
  bottom: 12px;
  width: 3px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
}
.steps-fill {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--petrol-400), var(--petrol-700));
  transform: scaleY(var(--p, 0));
  transform-origin: top center;
  transition: transform 0.15s linear;
}

.step { position: relative; }
.step-dot {
  position: absolute;
  left: calc(clamp(3rem, 2rem + 2vw, 4.5rem) * -1);
  top: 2px;
  width: clamp(2.6rem, 2rem + 1.6vw, 3.4rem);
  height: clamp(2.6rem, 2rem + 1.6vw, 3.4rem);
  border-radius: 999px;
  background: #fff;
  box-shadow: inset 0 0 0 2px var(--line);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 1.1875rem;
  font-weight: 600;
  color: var(--ink-3);
  transition: transform 0.5s var(--spring), color 0.3s var(--ease), box-shadow 0.3s var(--ease), background 0.3s var(--ease);
}
.band .step-dot { background: var(--paper-warm); }
.step.on .step-dot {
  background: var(--petrol-700);
  color: #fff;
  box-shadow: inset 0 0 0 2px var(--petrol-700), 0 8px 20px rgba(3, 105, 116, 0.28);
  transform: scale(1.06);
}
.step h3 { margin-bottom: 0.5rem; }
.step p { max-width: 52ch; }
.step-extra {
  margin-top: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* --------------------------------------------------------------------------
   The one surviving micro-demonstration: the pre-publish check, on features.html
   -------------------------------------------------------------------------- */

.demo-seo { display: grid; gap: 8px; }
.ds-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink-2);
  transition: opacity 0.4s var(--ease);
}
.js .ds-row { opacity: 0.35; }
.ds-box {
  width: 22px; height: 22px;
  border-radius: 7px;
  background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--line);
  display: grid;
  place-items: center;
  flex: none;
  transition: background 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.ds-box svg { width: 12px; height: 12px; color: #fff; transition: transform 0.35s var(--spring); }
.js .ds-box svg { transform: scale(0); }
.demo.go .ds-row { animation: dsOn 0.4s var(--ease) forwards; }
.demo.go .ds-row:nth-child(1) { animation-delay: 0.3s; }
.demo.go .ds-row:nth-child(2) { animation-delay: 0.75s; }
.demo.go .ds-row:nth-child(3) { animation-delay: 1.2s; }
.demo.go .ds-row:nth-child(4) { animation-delay: 1.65s; }
@keyframes dsOn { to { opacity: 1; } }
.demo.go .ds-row .ds-box { animation: dsBox 0.4s var(--ease) forwards; animation-delay: inherit; }
.demo.go .ds-row:nth-child(1) .ds-box { animation-delay: 0.3s; }
.demo.go .ds-row:nth-child(2) .ds-box { animation-delay: 0.75s; }
.demo.go .ds-row:nth-child(3) .ds-box { animation-delay: 1.2s; }
.demo.go .ds-row:nth-child(4) .ds-box { animation-delay: 1.65s; }
@keyframes dsBox { to { background: var(--petrol-700); box-shadow: inset 0 0 0 1.5px var(--petrol-700); } }
.demo.go .ds-row .ds-box svg { transform: scale(1); transition-delay: inherit; }
.demo.go .ds-row:nth-child(1) .ds-box svg { transition-delay: 0.45s; }
.demo.go .ds-row:nth-child(2) .ds-box svg { transition-delay: 0.9s; }
.demo.go .ds-row:nth-child(3) .ds-box svg { transition-delay: 1.35s; }
.demo.go .ds-row:nth-child(4) .ds-box svg { transition-delay: 1.8s; }

/* --------------------------------------------------------------------------
   The service counter + booking sheet (dark band)
   -------------------------------------------------------------------------- */

.counter {
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.055);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.13);
  padding: clamp(1.25rem, 0.9rem + 1.4vw, 1.85rem);
  backdrop-filter: blur(6px);
}
.counter-top { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.35rem; }
.counter-top b { color: #fff; font-size: 1.0625rem; }
.counter-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.cstat b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 1.4rem + 2.4vw, 3rem);
  font-weight: 600;
  color: #fff;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.cstat span { display: block; margin-top: 0.4rem; font-size: var(--t-micro); font-weight: 700; color: #a3c9d0; }
.cstat.amber b { color: #fcd34d; }

.meter { margin-top: 1.5rem; }
.meter-head { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--t-micro); font-weight: 700; color: #a3c9d0; margin-bottom: 0.5rem; }
.meter-head b { color: #dff1f4; }
.meter-track { height: 10px; border-radius: 999px; background: rgba(255,255,255,0.12); overflow: hidden; }
.meter-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--petrol-400), var(--petrol-200));
  transform-origin: left center;
  transition: transform 1.4s var(--ease-out) 0.2s;
}
.js .meter-fill { transform: scaleX(0); }
.meter.in .meter-fill { transform: scaleX(var(--f, 0.6)); }

.sheet { display: grid; gap: 0.6rem; margin-top: 1.5rem; }
.sheet-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.85rem 1rem;
  border-radius: 14px;
  background: rgba(255,255,255,0.05);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1);
}
.sheet-row .t { font-variant-numeric: tabular-nums; font-weight: 800; color: #fff; font-size: 1.0625rem; }
.sheet-row .n { color: #dff1f4; font-weight: 700; }
.sheet-row .n small { display: block; font-size: var(--t-micro); font-weight: 600; color: #a3c9d0; }
.pill {
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 800;
  white-space: nowrap;
}
.pill-ok { background: rgba(16, 185, 129, 0.18); color: #6ee7b7; }
.pill-wait { background: rgba(251, 191, 36, 0.16); color: #fcd34d; }
.pill-seat { background: rgba(184, 231, 238, 0.16); color: var(--petrol-200); }

/* --------------------------------------------------------------------------
   Stat strip
   -------------------------------------------------------------------------- */

.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1rem, 0.6rem + 1.4vw, 2rem); }
.stat b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 1.5rem + 2.6vw, 3.4rem);
  font-weight: 600;
  color: var(--petrol-700);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.stat span { display: block; margin-top: 0.6rem; font-size: var(--t-small); font-weight: 600; color: var(--ink-2); max-width: 22ch; }

/* --------------------------------------------------------------------------
   Pricing
   -------------------------------------------------------------------------- */

/* The three cards are the same height whatever their lists say, and the meters
   line up along the bottom, because a price comparison read across three ragged
   columns is harder than it needs to be. */
/* Four tiers since Max. Two across between 960px and 1200px, because four
   1fr columns in that band give a card too narrow for the price and the
   billing line to sit on one row each. Below 960px the rule further down
   takes over and stacks them. */
.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1rem, 0.5rem + 1.6vw, 1.5rem); align-items: stretch; }
@media (max-width: 1200px) { .plans { grid-template-columns: repeat(2, 1fr); } }

.plan {
  position: relative;
  background: #fff;
  border-radius: var(--r-lg);
  box-shadow: inset 0 0 0 1px var(--line);
  padding: clamp(1.5rem, 1rem + 1.5vw, 2.15rem);
  display: flex;
  flex-direction: column;
  transition: transform 0.4s var(--ease-out);
  isolation: isolate;
}
/* FOUR CARDS ACROSS TAKE A TIGHTER GUTTER INSIDE THE CARD, and the reason is
   one measurement rather than taste. At four up the card is 272px and its
   own padding leaves 203px of content; `$24.99 / month` needs 209px and
   `$39.99 / month` needs 212px, so the two dearest prices wrapped onto a
   second line while `$0` and `$9.99` did not — the price row standing 76px
   tall on two cards and 50px on the other two, which reads as a rendering
   fault rather than as a price. 1.75rem of padding gives 216px and clears
   the widest of them with 4px to spare.
   The type does NOT shrink to fit: the container gives way, which is this
   app's standing repair. Re-check with `node .zz-plan4-marketing.mjs` if a
   price ever gains a digit. */
@media (min-width: 1201px) { .plan { padding: 1.75rem; } }
.plan::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  box-shadow: var(--sh-2);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
}
.plan:hover { transform: translateY(-6px); }
.plan:hover::before { opacity: 1; }

.plan-best { box-shadow: inset 0 0 0 2px var(--petrol-700); }
.plan-best::after {
  content: "";
  position: absolute; inset: -6px; z-index: -2;
  border-radius: calc(var(--r-lg) + 6px);
  box-shadow: 0 18px 50px rgba(4, 129, 142, 0.26);
  animation: breathe 5s var(--ease) infinite alternate;
}
@keyframes breathe { from { opacity: 0.4; } to { opacity: 1; } }

.plan-flag {
  position: absolute;
  top: -14px; left: 50%;
  transform: translateX(-50%);
  padding: 0.35rem 0.95rem;
  border-radius: 999px;
  background: var(--petrol-700);
  color: #fff;
  font-size: var(--t-micro);
  font-weight: 800;
  white-space: nowrap;
  box-shadow: 0 6px 16px rgba(3, 105, 116, 0.3);
}
.plan h3 { font-size: 1.4375rem; margin-bottom: 0.35rem; }
.plan .blurb { font-size: var(--t-small); color: var(--ink-3); min-height: 3rem; }
.plan-price { display: flex; align-items: baseline; gap: 0.35rem; margin: 1.25rem 0 0.25rem; }
.plan-price b {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 1.8rem + 2vw, 3.1rem);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.03em;
  line-height: 1;
}
.plan-price span { font-size: var(--t-small); font-weight: 700; color: var(--ink-3); }
.plan-per { font-size: var(--t-micro); color: var(--ink-3); margin-bottom: 1.5rem; }
.plan .btn { margin-bottom: 1.6rem; }
.plan-list { list-style: none; display: grid; gap: 0.8rem; font-size: var(--t-small); }
.plan-list li { display: flex; gap: 0.7rem; align-items: flex-start; }
.plan-list li span:last-child { padding-top: 0.15rem; }
.plan-list .off { color: var(--ink-3); }
.plan-list { margin-bottom: auto; }
.plan-sep { margin: 1.35rem 0 0; height: 1px; background: var(--line); }
.plan-meters { display: grid; gap: 0.55rem; font-size: var(--t-micro); padding-top: 1.35rem; }
.plan-meters div { display: flex; justify-content: space-between; gap: 1rem; }
.plan-meters b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* Comparison table */
.tbl-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tbl { width: 100%; border-collapse: collapse; min-width: 620px; }
.tbl th, .tbl td { padding: 1rem 1.1rem; text-align: left; border-bottom: 1px solid var(--line); }
.tbl thead th {
  font-family: var(--font-sans);
  font-size: var(--t-micro);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 2px solid var(--line);
  position: sticky;
  top: 0;
  background: #fff;
}
.tbl tbody th { font-weight: 600; color: var(--ink); font-family: var(--font-sans); font-size: var(--t-small); }
.tbl td { text-align: center; }
.tbl th:first-child { text-align: left; }
.tbl tbody tr:hover { background: var(--petrol-50); }
.tbl .num { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); }
.tbl .best-col { background: rgba(237, 250, 252, 0.55); }

/* --------------------------------------------------------------------------
   Quote / callout
   -------------------------------------------------------------------------- */

.callout {
  border-radius: var(--r-lg);
  background: var(--petrol-50);
  box-shadow: inset 0 0 0 1px var(--petrol-200);
  padding: clamp(1.35rem, 1rem + 1.4vw, 2rem);
  display: flex;
  gap: 1.1rem;
  align-items: flex-start;
}
.callout svg { width: 26px; height: 26px; color: var(--petrol-700); flex: none; margin-top: 2px; }
.callout p { color: var(--petrol-900); }
.callout b { color: var(--petrol-950); }

/* --------------------------------------------------------------------------
   Final call to action
   -------------------------------------------------------------------------- */

.cta-band { position: relative; overflow: clip; }
.cta-band .wrap { text-align: center; }
.cta-band h2 { font-size: clamp(2.1rem, 1.4rem + 2.8vw, 3.6rem); margin-bottom: 1.1rem; }
.cta-band .lead { margin-inline: auto; max-width: 50ch; }
.cta-band .btn-row { justify-content: center; margin-top: 2.25rem; }

/* --------------------------------------------------------------------------
   Auth screens
   --------------------------------------------------------------------------
   Deliberately drawn in the product's own flat grammar: a mark, a 2px rule
   opening the block, a heading, one plain line, then the controls, inside one
   25rem measure. The BLOCK is centred in the window; its CONTENTS are not,
   centring ragged text over left-anchored controls is what reads as broken.
   No card: no fill, no edge, no radius, no cast.
   -------------------------------------------------------------------------- */

.auth-page { min-height: 100dvh; display: grid; grid-template-rows: auto 1fr auto; background: #fff; }
.auth-main { display: grid; place-items: center; padding: clamp(2rem, 1rem + 4vw, 4rem) var(--gut); position: relative; }
.auth-glow { position: absolute; inset: 0; overflow: clip; pointer-events: none; z-index: 0; }
.auth-glow i {
  position: absolute;
  display: block;
  width: 46vw; height: 46vw; min-width: 400px; min-height: 400px;
  border-radius: 50%;
  filter: blur(100px);
  opacity: 0.42;
}
.auth-glow i:nth-child(1) { left: -12vw; bottom: -14vw; background: radial-gradient(circle, rgba(143,210,219,0.6), rgba(143,210,219,0) 70%); animation: drift1 24s var(--ease) infinite alternate; }
.auth-glow i:nth-child(2) { right: -10vw; top: -16vw; background: radial-gradient(circle, rgba(216,244,248,0.9), rgba(216,244,248,0) 70%); animation: drift2 30s var(--ease) infinite alternate; }

.auth-block { position: relative; z-index: 1; width: 100%; max-width: 25rem; }
/* The auth pages kept a full-width rule for a while. With every other bar on
   the site gone it was the only one left, which made it read as a leftover
   rather than as a masthead line, so it went too. */
.auth-block .rule { display: none; }
.auth-block h1 { font-size: clamp(1.9rem, 1.5rem + 1.4vw, 2.35rem); margin-bottom: 0.6rem; }
.auth-block .sub { font-size: var(--t-small); color: var(--ink-3); margin-bottom: 2rem; }
.auth-alt { margin-top: 1.75rem; font-size: var(--t-small); color: var(--ink-3); }
.auth-alt a { font-weight: 700; }
.auth-foot { padding: 1.5rem var(--gut) 2rem; text-align: center; font-size: var(--t-micro); color: var(--ink-3); }
.auth-foot a { color: var(--ink-3); }

.auth-side { display: grid; gap: 1rem; align-content: center; }
.auth-side .card { padding: 1.35rem 1.5rem; }
.auth-side .card :is(h2, h3) { margin-bottom: 0.4rem; font-size: 1.25rem; }
.auth-side .icon-badge { width: 42px; height: 42px; border-radius: 13px; margin-bottom: 0.85rem; }
.auth-side .icon-badge svg { width: 20px; height: 20px; }
.auth-two {
  display: grid;
  grid-template-columns: minmax(0, 25rem) minmax(0, 24rem);
  justify-content: center;
  gap: clamp(2rem, 1rem + 4vw, 4.5rem);
  width: 100%;
  max-width: 58rem;
  align-items: center;
}

/* --------------------------------------------------------------------------
   Page header for sub-pages
   -------------------------------------------------------------------------- */

.page-head { position: relative; padding-block: clamp(3rem, 2rem + 4vw, 5.5rem) clamp(2.5rem, 1.5rem + 3vw, 4rem); overflow: clip; }
.page-head h1 { margin-block: 1.2rem 1.4rem; font-size: clamp(2.4rem, 1.7rem + 3.2vw, 4rem); }
.page-head .lead { max-width: 52ch; }

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1080px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero .lead { max-width: 52ch; }
  /* 620px × 1.3, the same 30% the two-column layout takes from the window's
     margin. There is room for it here: one column at 1080px is a 1005px
     measure, so this is a cap the picture reaches rather than a width it
     fights for. */
  .stage { max-width: 806px; margin-inline: auto; }
  .frame { transform: none; }
  .stage:hover .frame { transform: none; }
}

/* The top bar carries five links now that Home is one of them, so it needs a
   breakpoint of its own: it runs out of room before the page layout does. */
@media (max-width: 1150px) {
  .nav { display: none; }
  .topbar-cta .btn-ghost { display: none; }
  .burger { display: grid; }
}

@media (max-width: 960px) {
  .split, .split-wide, .split-lead { grid-template-columns: minmax(0, 1fr); }
  .split-flip > *:first-child { order: 2; }
  .assur-strip { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .plans { grid-template-columns: minmax(0, 1fr); max-width: 32rem; margin-inline: auto; }
  .plan-best { order: -1; }
  .footer-grid { grid-template-columns: repeat(2, 1fr); }
  .auth-two { grid-template-columns: minmax(0, 1fr); }
  .auth-side { display: none; }
}

@media (max-width: 720px) {
  /* The positioning line goes earlier than it used to. It sat UNDER the product's
     name inside the old lockup, so it cost height the bar already had and was
     kept down to 520px; beside the logo it costs width, which is the thing the
     bar runs out of. The logo carries the name either way. */
  .brand-tag { display: none; }
  .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
  .counter-grid { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; }
  .cstat { display: flex; align-items: baseline; gap: 0.75rem; }
  .cstat span { margin-top: 0; }
  .sheet-row { grid-template-columns: auto 1fr; }
  .sheet-row .pill { grid-column: 2; justify-self: start; }
  .mobile-nav { inset-block-start: 68px; }
  .topbar-in { min-height: 68px; }
}

/* Under this width the product's name, one call to action and a menu button
   cannot all fit without something wrapping, and a wrapped brand reads as a
   broken page. The call to action goes, because it is 300px below in the hero
   and it is the first thing inside the menu. */
@media (max-width: 560px) {
  .topbar-cta .btn-primary { display: none; }
}

@media (max-width: 520px) {
  .assur-strip { grid-template-columns: minmax(0, 1fr); }
  .stats { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .stat { display: flex; align-items: baseline; gap: 1rem; }
  .stat span { margin-top: 0; }
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
  .btn { width: 100%; }
  .btn-row { flex-direction: column; align-items: stretch; }
  .topbar-cta .btn { width: auto; white-space: nowrap; padding-inline: 1rem; }
  .brand-logo { height: 34px; }
}


/* --------------------------------------------------------------------------
   “What's in it”: one panel, everything in it
   --------------------------------------------------------------------------
   Three columns of ticked items under a dark head, closed by a warm foot. It
   is a list rather than a demonstration, deliberately: the job of that section
   is to settle "is this actually enough?" inside one screen, and the count is
   what does the arguing. It also needs no photography, which is why it is the
   one part of the page that looks finished before the real pictures arrive.

   Chosen from four directions drawn against the real stylesheet; the other
   three are gone.
   -------------------------------------------------------------------------- */

.inbox { background: #fff; border-radius: var(--r-xl); box-shadow: inset 0 0 0 1px var(--line), var(--sh-1); overflow: hidden; }

.inbox-top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1.5rem;
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem) clamp(1.5rem, 1rem + 1.6vw, 2.25rem);
  background: var(--petrol-950);
  color: #fff;
}
.inbox-top b { font-family: var(--font-display); font-size: clamp(1.25rem, 1.1rem + 0.8vw, 1.6rem); }
.inbox-top span { font-size: var(--t-small); color: #a3c9d0; margin-left: auto; }

.inbox-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.inbox-col { padding: clamp(1.35rem, 1rem + 1.2vw, 2rem); }
.inbox-col + .inbox-col { border-left: 1px solid var(--line); }
.inbox-col :is(h3, h4) {
  font-family: var(--font-sans);
  font-size: var(--t-micro);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.1rem;
}
.inbox-col ul { list-style: none; display: grid; gap: 0.85rem; }
.inbox-col li { display: flex; gap: 0.7rem; align-items: flex-start; font-size: var(--t-small); }
.inbox-col li b { display: block; color: var(--ink); font-weight: 700; }
.inbox-col li small { display: block; font-size: var(--t-micro); color: var(--ink-3); margin-top: 2px; }

.inbox-foot {
  padding: 1.25rem clamp(1.5rem, 1rem + 1.6vw, 2.25rem);
  background: var(--paper-warm);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  justify-content: space-between;
}

@media (max-width: 860px) {
  .inbox-cols { grid-template-columns: minmax(0, 1fr); }
  .inbox-col + .inbox-col { border-left: 0; border-top: 1px solid var(--line); }
}


/* --------------------------------------------------------------------------
   The cost comparison, on the pricing page
   --------------------------------------------------------------------------
   What a website normally costs a restaurant, struck through, against one
   price. The strike goes on the NAME only: put it on the row and it draws
   straight through the explanation underneath, which is the half that wants
   reading.
   -------------------------------------------------------------------------- */

.versus { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: clamp(2rem, 1rem + 3vw, 3.5rem); align-items: center; }
.versus-list { display: grid; gap: 0.6rem; }

.versus-old {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.95rem 1.1rem;
  border-radius: 14px;
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--line);
}
.versus-old .t { color: var(--ink-3); }
.versus-old .t b { font-weight: 700; text-decoration: line-through; text-decoration-color: rgba(11, 30, 34, 0.3); }
.versus-old .t small { display: block; font-size: var(--t-micro); color: var(--ink-3); font-weight: 500; margin-top: 2px; }
.versus-old .c { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 800; color: var(--ink-3); white-space: nowrap; }

.versus-sum { display: flex; align-items: baseline; gap: 0.75rem; padding: 0.5rem 1.1rem 0; font-size: var(--t-small); color: var(--ink-3); }
.versus-sum b { margin-left: auto; font-size: 1.1875rem; color: var(--ink); font-variant-numeric: tabular-nums; }

.versus-card {
  background: var(--petrol-950);
  color: #cfe9ed;
  border-radius: var(--r-xl);
  padding: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
  text-align: center;
  box-shadow: var(--sh-3);
}
.versus-card .eyebrow { color: var(--petrol-300); justify-content: center; }
.versus-card b.price {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(3rem, 2rem + 4vw, 4.5rem);
  color: #fff;
  line-height: 1;
  letter-spacing: -0.03em;
  margin: 0.75rem 0 0.35rem;
}
.versus-card .per { font-size: var(--t-small); color: #a3c9d0; }
.versus-card ul { list-style: none; display: grid; gap: 0.55rem; margin: 1.75rem 0; text-align: left; font-size: var(--t-small); }
.versus-card li { display: flex; gap: 0.6rem; align-items: flex-start; }

@media (max-width: 860px) { .versus { grid-template-columns: minmax(0, 1fr); } }

/* Print: an owner may well print the pricing page. */
@media print {
  .topbar, .mobile-nav, .hero-glow, .auth-glow, .cta-band, .footer { display: none !important; }
  body { color: #000; }
  .rise, .rise-l, .rise-r, .rise-scale { opacity: 1 !important; transform: none !important; }
}
