/* ==========================================================================
   Restodoo — Odoo 20 for restaurants

   Warm cream paper, dark aubergine, orange accents. Receipt detailing:
   perforated edges, monospace figures, dotted leader lines.

   The [data-reveal] / [data-parallax] contracts and the .is-in class are what
   js/main.js drives — keep those names if you restyle.
   ========================================================================== */

/* ---------- Typefaces, served from here ----------
   These used to load from Google Fonts, which put every visitor's IP address
   in front of Google before the page had painted — a transfer the privacy
   policy then had to disclose. The files under assets/fonts/ are the ones
   Google serves, latin and latin-ext subsets only (NL, FR and EN need nothing
   else). Each upright file is a variable font, so one file covers the whole
   weight range the page uses; the range in font-weight is what tells the
   browser that. Add a weight outside it and the browser synthesises, badly. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("../assets/fonts/fraunces-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: "Fraunces";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("../assets/fonts/fraunces-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: "Fraunces";
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../assets/fonts/fraunces-italic-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: "Fraunces";
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../assets/fonts/fraunces-italic-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: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../assets/fonts/instrument-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;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../assets/fonts/instrument-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: "Instrument Sans";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/instrument-sans-italic-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: "Instrument Sans";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/instrument-sans-italic-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: "Fragment Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/fragment-mono-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: "Fragment Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/fragment-mono-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;
}

:root {
  /* Paper */
  --cream: #f7f0e4;
  --cream-deep: #efe5d3;       /* alternating band */
  --paper: #fffaf1;            /* receipts sit slightly brighter than the page */

  /* Aubergine */
  --aub: #2d1b2e;
  --aub-soft: #432c44;
  --aub-dim: rgba(45, 27, 46, .62);
  --aub-faint: rgba(45, 27, 46, .12);

  /* Accent */
  --orange: #e2701f;
  --orange-deep: #c25c12;
  --orange-soft: rgba(226, 112, 31, .13);

  --font-display: "Fraunces", Georgia, serif;
  --font-body: "Instrument Sans", system-ui, sans-serif;
  --font-mono: "Fragment Mono", ui-monospace, monospace;

  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --pad: clamp(1.25rem, 4vw, 4rem);
}

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

html { scroll-behavior: smooth; scroll-padding-top: 5.5rem; }

body {
  background: var(--cream);
  color: var(--aub);
  font-family: var(--font-body);
  font-size: clamp(1rem, .95rem + .3vw, 1.12rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video { display: block; max-width: 100%; }
a { color: inherit; }
::selection { background: var(--orange); color: #fff; }
:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; }

/* ---------- Reveal system (JS toggles .is-in) ---------- */

[data-reveal] {
  opacity: 0;
  transition:
    opacity 1s var(--ease-out) var(--d, 0s),
    transform 1s var(--ease-out) var(--d, 0s);
  will-change: opacity, transform;
}
[data-reveal="up"]     { transform: translateY(2.5rem); }
[data-reveal="grow"]   { transform: translateY(2rem) scale(.95); }
[data-reveal="side-l"] { transform: translateX(-3.5rem); }
[data-reveal="side-r"] { transform: translateX(3.5rem); }
[data-reveal="line"]   { display: inline-block; transform: translateY(110%); }
[data-reveal].is-in    { opacity: 1; transform: none; }

[data-reveal="words"] { opacity: 1; transform: none; }
[data-reveal="words"] .w {
  display: inline-block;
  opacity: .16;
  transform: translateY(.35em);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
}
[data-reveal="words"] .w.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-reveal="words"] .w {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .tape__track, .route__arrow { animation: none !important; }
}

/* ---------- Receipt paper ----------
   Perforated top and bottom edges, punched with a mask so they work over any
   background. Masked boxes clip borders and shadows, so receipts are flat by
   design — which is what a till receipt looks like anyway. */

.receipt {
  --tooth: 9px;
  background: var(--paper);
  -webkit-mask:
    radial-gradient(var(--tooth) at 50% 0, #0000 98%, #000) 50% 0 / calc(2 * var(--tooth)) var(--tooth) repeat-x,
    radial-gradient(var(--tooth) at 50% 100%, #0000 98%, #000) 50% 100% / calc(2 * var(--tooth)) var(--tooth) repeat-x,
    linear-gradient(#000 0 0) 50% 50% / 100% calc(100% - 2 * var(--tooth)) no-repeat;
  mask:
    radial-gradient(var(--tooth) at 50% 0, #0000 98%, #000) 50% 0 / calc(2 * var(--tooth)) var(--tooth) repeat-x,
    radial-gradient(var(--tooth) at 50% 100%, #0000 98%, #000) 50% 100% / calc(2 * var(--tooth)) var(--tooth) repeat-x,
    linear-gradient(#000 0 0) 50% 50% / 100% calc(100% - 2 * var(--tooth)) no-repeat;
}

/* Dotted leader between a line item and its value, the way a bill sets it. */
.leader {
  flex: 1;
  align-self: end;
  min-width: 1.2rem;
  height: .75em;
  border-bottom: 1.5px dotted rgba(45, 27, 46, .32);
}

/* ---------- Placeholder markers ----------
   Anything standing in for real content wears one of these, so an unfinished
   page is obvious instead of shipping by accident. Grep for them. */

.ph-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--orange-deep);
  border: 1px dashed rgba(226, 112, 31, .6);
  border-radius: 100px;
  padding: .4em 1em;
  background: var(--orange-soft);
}
.ph-badge--wide { margin-top: 1.4rem; }
.placeholder { color: var(--orange-deep); border-bottom: 2px dotted rgba(226, 112, 31, .65); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: .98rem;
  text-decoration: none;
  padding: .9em 1.8em;
  border-radius: 100px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .35s var(--ease-out), background .35s, color .35s, box-shadow .35s, border-color .35s;
}
.btn--accent {
  background: var(--orange);
  color: #fff;
  box-shadow: 0 8px 26px rgba(226, 112, 31, .3);
}
.btn--accent:hover {
  background: var(--orange-deep);
  transform: translateY(-3px);
  box-shadow: 0 14px 38px rgba(226, 112, 31, .42);
}
/* Ghost inverts with its surroundings: aubergine ink on paper, cream on dark. */
.btn--ghost {
  border-color: var(--aub-faint);
  color: var(--aub);
  background: rgba(45, 27, 46, .03);
}
.btn--ghost:hover { border-color: var(--aub); transform: translateY(-3px); }
.on-dark .btn--ghost,
.hero .btn--ghost,
.cta .btn--ghost {
  border-color: rgba(247, 240, 228, .3);
  color: var(--cream);
  background: rgba(247, 240, 228, .06);
  backdrop-filter: blur(6px);
}
.hero .btn--ghost:hover,
.cta .btn--ghost:hover { border-color: var(--cream); }

/* ---------- Section heads ---------- */

.section-head { padding: 0 var(--pad); max-width: 78rem; margin: 0 auto 3.4rem; }
.section-head--center { text-align: center; }
.section-head--center .section-head__sub { margin-inline: auto; }
.section-head__label {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--orange-deep);
}
.section-head__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.3rem, 5.6vw, 4.4rem);
  line-height: 1.04;
  letter-spacing: -.02em;
  margin-top: .7rem;
}
.section-head__sub { color: var(--aub-dim); max-width: 38rem; margin-top: 1.2rem; }

/* ---------- Nav ---------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem var(--pad);
  transition: background .5s, padding .5s, border-color .5s, color .5s;
  border-bottom: 1px solid transparent;
  /* Over the hero photograph the nav is light; once scrolled it becomes paper. */
  color: var(--cream);
}
.nav.is-scrolled {
  background: rgba(255, 250, 241, .92);
  backdrop-filter: blur(14px);
  border-color: var(--aub-faint);
  padding-block: .7rem;
  color: var(--aub);
}
.nav__logo,
.footer__brand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.12rem;
  letter-spacing: .1em;
  text-decoration: none;
}
.nav__logo em,
.footer__brand em { font-style: normal; color: var(--orange); }

.nav__mark { display: block; width: 1.25rem; flex: none; }
.nav__mark svg { width: 100%; height: auto; fill: none; stroke-linecap: round; }
.mark-fork { stroke: var(--orange); stroke-width: 2.4; }
.mark-knife { stroke: currentColor; stroke-width: 2.4; }

.nav__links { display: flex; gap: 1.8rem; }
.nav__links a {
  text-decoration: none;
  font-size: .94rem;
  color: inherit;
  opacity: .78;
  transition: opacity .3s;
  position: relative;
}
.nav__links a::after {
  content: "";
  position: absolute; left: 0; bottom: -6px;
  width: 100%; height: 2px;
  background: var(--orange);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s var(--ease-out);
}
.nav__links a:hover { opacity: 1; }
.nav__links a:hover::after { transform: scaleX(1); }

.nav__cta { font-size: .86rem; padding: .66em 1.35em; }
.nav__right { display: flex; align-items: center; gap: .85rem; }

/* Segmented language pill — orange glider slides behind the active language */
.nav__lang {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  padding: .25rem;
  border: 1px solid currentColor;
  border-radius: 100px;
  opacity: .9;
}
.nav__lang::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: .25rem; bottom: .25rem; left: .25rem;
  width: calc((100% - .5rem) / 3);
  border-radius: 100px;
  background: var(--orange);
  transition: transform .45s var(--ease-out);
}
.nav__lang:has([data-lang="nl"].is-active)::before { transform: translateX(100%); }
.nav__lang:has([data-lang="fr"].is-active)::before { transform: translateX(200%); }
.lang-btn {
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .1em;
  color: inherit;
  opacity: .7;
  width: 2.5rem;
  padding: .5em 0;
  text-align: center;
  border-radius: 100px;
  transition: opacity .35s, color .35s;
}
.lang-btn:hover { opacity: 1; }
.lang-btn.is-active { color: #fff; opacity: 1; }

/* ---------- Section menu ---------- */

.nav__menu {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 1px solid currentColor;
  border-radius: 100px;
  background: none;
  color: inherit;
  cursor: pointer;
  opacity: .9;
  transition: opacity .35s;
}
.nav__menu:hover { opacity: 1; }
.nav__burger { position: relative; }
.nav__burger,
.nav__burger::before,
.nav__burger::after {
  display: block;
  width: 1rem;
  height: 1.5px;
  border-radius: 2px;
  background: currentColor;
  transition: transform .35s var(--ease-out), background .2s;
}
.nav__burger::before,
.nav__burger::after { content: ""; position: absolute; left: 0; }
.nav__burger::before { top: -5px; }
.nav__burger::after { top: 5px; }
/* Open: the three bars fold into a close cross. */
[aria-expanded="true"] .nav__burger { background: transparent; }
[aria-expanded="true"] .nav__burger::before { transform: translateY(5px) rotate(45deg); }
[aria-expanded="true"] .nav__burger::after { transform: translateY(-5px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: 0 0 auto 0;
  /* Below the nav, so the toggle stays clickable while the panel is open. */
  z-index: 99;
  max-height: 100svh;
  overflow-y: auto;
  padding: 5.6rem var(--pad) 2.4rem;
  background: var(--paper);
  border-bottom: 1px solid var(--aub-faint);
  box-shadow: 0 30px 60px rgba(45, 27, 46, .14);
  opacity: 0;
  transform: translateY(-1rem);
  pointer-events: none;
  transition: opacity .3s var(--ease-out), transform .4s var(--ease-out);
}
.menu.is-open { opacity: 1; transform: none; pointer-events: auto; }
/* Closed for real once the fade is done — and from the start without JS. */
.menu[hidden] { display: none; }

.menu__inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: 2rem 2.5rem;
  max-width: 68rem;
  margin: 0 auto;
}
.menu__group { display: flex; flex-direction: column; align-items: start; gap: .5rem; }
.menu__label {
  margin: 0 0 .3rem;
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--orange-deep);
  text-decoration: none;
}
a.menu__label:hover { color: var(--aub); }
.menu__link {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.12rem;
  color: var(--aub-dim);
  text-decoration: none;
  transition: color .3s, transform .3s var(--ease-out);
}
.menu__link:hover { color: var(--aub); transform: translateX(4px); }

.menu__foot { display: none; margin-top: 2rem; }
.menu .nav__lang { display: none; color: var(--aub); }

@media (prefers-reduced-motion: reduce) {
  .menu { transition: none; }
  .menu__link:hover { transform: none; }
}

@media (max-width: 860px) {
  .nav__links { display: none; }
  /* No room for the pill beside the logo, CTA and toggle — it moves into the menu. */
  .nav__right .nav__lang { display: none; }
  .menu__foot { display: flex; justify-content: center; }
  .menu .nav__lang { display: flex; }
}

/* Narrow phones: logo + CTA + toggle only just fit, and the French CTA is the
   longest of the three languages — trim all three rather than drop any. */
@media (max-width: 480px) {
  .nav__logo { font-size: .95rem; letter-spacing: .06em; }
  .nav__right { gap: .45rem; }
  .nav__cta { font-size: .76rem; padding: .6em .95em; }
  .nav__menu { width: 2.25rem; height: 2.25rem; }
  .nav__mark { width: 1.05rem; }
}

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

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: center;
  overflow: hidden;
  padding: 7rem var(--pad) 5rem;
  color: var(--cream);
}
.hero__media { position: absolute; inset: -10% 0; z-index: -2; }
.hero__img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* A very slow push in, so the still is never quite static. */
  animation: heroPush 26s ease-in-out infinite alternate;
}
@keyframes heroPush {
  from { transform: scale(1.04); }
  to   { transform: scale(1.13); }
}
@media (prefers-reduced-motion: reduce) {
  .hero__img { animation: none; transform: none; }
}
.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(105deg, rgba(45,27,46,.93) 0%, rgba(45,27,46,.74) 45%, rgba(45,27,46,.42) 100%),
    linear-gradient(180deg, transparent 60%, var(--cream) 100%);
}
.hero__content { max-width: 58rem; position: relative; }
.hero__kicker {
  font-family: var(--font-mono);
  font-size: .76rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 1.5rem;
}
.hero__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.8rem, 8.5vw, 6.6rem);
  line-height: .98;
  letter-spacing: -.03em;
}
.hero__line { display: block; overflow: hidden; }
.hero__line--accent { color: var(--orange); }
.hero__sub { max-width: 37rem; margin-top: 1.8rem; color: rgba(247, 240, 228, .82); }
/* A one-line promise ahead of the explanation, set as its own line in full
   cream — the NL copy opens that way; the dictionary carries the <strong>. */
.hero__sub strong { display: block; margin-bottom: .55rem; font-weight: 600; color: var(--cream); }
.hero__actions { display: flex; flex-wrap: wrap; gap: .9rem; margin-top: 2.2rem; }
.hero__note {
  margin-top: 1.1rem;
  font-family: var(--font-mono);
  font-size: .76rem;
  color: rgba(247, 240, 228, .6);
}

/* ---------- Receipt tape ---------- */

.tape {
  overflow: hidden;
  background: var(--paper);
  padding-block: .85rem;
  /* Perforated top and bottom, like a strip torn from a till roll. */
  border-block: 1.5px dashed var(--aub-faint);
}
.tape__track { display: flex; width: max-content; animation: slide 36s linear infinite; }
.tape__track span {
  font-family: var(--font-mono);
  font-size: .76rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--aub-dim);
  padding-right: 1rem;
}
@keyframes slide { to { transform: translateX(-50%); } }

/* ---------- Service situations ---------- */

.service { padding-block: clamp(4rem, 10vw, 7rem); }
.situations {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  max-width: 78rem;
  margin: 0 auto;
  padding: 0 var(--pad);
}
.sit {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
}
.sit--flip .sit__photo { order: 2; }
.sit__photo {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 18px;
  overflow: hidden;
  background: var(--cream-deep);
}
.sit__photo img { width: 100%; height: 100%; object-fit: cover; }
.sit__num {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .18em;
  color: var(--orange-deep);
}
/* The situation is a quote, so it is set like one. */
.sit__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-style: italic;
  font-size: clamp(1.5rem, 3.2vw, 2.3rem);
  line-height: 1.15;
  letter-spacing: -.015em;
  margin: .6rem 0 .9rem;
}
.sit__text { color: var(--aub-dim); max-width: 34rem; }

@media (max-width: 760px) {
  .sit { grid-template-columns: 1fr; }
  .sit--flip .sit__photo { order: 0; }
}

/* ---------- Real Odoo screens ----------
   Section 03: unedited screenshots, so they get a plain paper plate and a
   hairline edge rather than a dark device frame. Nothing here borrows Odoo's
   visual identity — the screens bring their own, inside our frame, which is
   the whole point of the frame. (This was the proof strip under a grid of
   clip slots until the slots went.) */

.screens { padding-block: clamp(4rem, 10vw, 7rem); background: var(--cream-deep); }

.screens__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(30rem, 100%), 1fr));
  gap: clamp(1.6rem, 3.4vw, 2.6rem);
  max-width: 78rem;
  margin: 0 auto;
  padding: 0 var(--pad);
}

.screen__frame {
  aspect-ratio: 16 / 10;          /* the shots are 2880×1800 — no cropping */
  border-radius: 12px;
  overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--aub-faint);
  box-shadow: 0 18px 40px rgba(45, 27, 46, .14);
}
.screen__img { width: 100%; height: 100%; object-fit: cover; display: block; }

.screen__cap { margin-top: 1rem; }
.screen__pair {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--orange-deep);
}
.screen__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.18rem;
  margin-top: .3rem;
}
.screen__text { color: var(--aub-dim); font-size: .95rem; margin-top: .3rem; }

/* ---------- Story ---------- */

.story { padding: clamp(4.5rem, 11vw, 8rem) var(--pad); max-width: 60rem; margin: 0 auto; }
.story__label {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--orange-deep);
  margin-bottom: 1.5rem;
}
.story__text {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.45rem, 3.2vw, 2.5rem);
  line-height: 1.26;
  letter-spacing: -.015em;
}
.story__text b { font-weight: 700; color: var(--orange-deep); }

/* ---------- Beyond the floor (section 04) ----------
   Four more Odoo screens, the same .screens__grid / .screen* treatment as
   section 03. This wrapper keeps the paper background (section 03 is
   cream-deep, and so is pricing right after this one) so the three do not
   merge into one band. The old download-card styles (.pack, .promo__grid)
   lived here and went with the cards. */

.promo { padding-block: clamp(4rem, 10vw, 7rem); }

/* ---------- How it's priced ----------
   No figures on the page: the section is the setup receipt below and the
   subsidy note inside it. The three tier receipts that used to sit above it
   went with the prices. */

.pricing { padding-block: clamp(4rem, 10vw, 7rem); background: var(--cream-deep); }

/* Setup: its own receipt, itemised like a bill. */
.setup {
  max-width: 54rem;
  margin: clamp(2.4rem, 5vw, 4rem) auto 0;
  margin-inline: var(--pad);
  padding: clamp(2.4rem, 4vw, 3.4rem) clamp(1.6rem, 3vw, 3rem);
  text-align: left;
}
@media (min-width: 60rem) { .setup { margin-inline: auto; } }
.setup__head { text-align: center; border-bottom: 1.5px dashed var(--aub-faint); padding-bottom: 1.6rem; }
.setup__label {
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--orange-deep);
}
.setup__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.7rem, 3.2vw, 2.4rem);
  line-height: 1.1;
  margin: .5rem 0 .8rem;
}
.setup__text { color: var(--aub-dim); font-size: .96rem; max-width: 34rem; margin-inline: auto; }
.setup__list { list-style: none; margin: 1.4rem 0; }
.setup__list li {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  padding: .5em 0;
  font-size: .94rem;
}
.setup__inc {
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--orange-deep);
}
/* Where the total used to be printed: the receipt now ends on the line that
   says the figure comes after the demo, ruled off like a total would be. */
.setup__excl {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--aub-dim);
  border-top: 2px solid var(--aub);
  padding-top: 1rem;
  margin-top: .6rem;
}
/* A third party paying part of one line of the bill, so it is set as something
   stamped onto the receipt rather than another item on it. */
.subsidy {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  margin-top: 1.5rem;
  padding: 1.1rem clamp(1rem, 2vw, 1.3rem);
  border: 1.5px dashed var(--aub-faint);
  background: rgba(226, 112, 31, .05);
}
.subsidy__head {
  display: flex;
  align-items: center;
  gap: .55rem;
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--orange-deep);
}
.subsidy__stamp {
  flex: none;
  width: .6rem;
  height: .6rem;
  border: 2px solid var(--orange);
  border-radius: 50%;
}
.subsidy__text { font-size: .92rem; }
.subsidy__text b { font-weight: 600; }
.subsidy__fine { font-size: .82rem; color: var(--aub-dim); }
.subsidy__nr {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--aub-dim);
}

.setup__btn { margin-top: 1.6rem; }

/* ---------- About ---------- */
/* The credentials reuse the setup receipt's itemised-line pattern rather than
   introducing a row of stat cards: the number that matters is already carried
   by the heading. */
.about { padding-block: clamp(4rem, 10vw, 7rem); }
.about__card {
  max-width: 48rem;
  margin-inline: var(--pad);
  margin-top: clamp(1.8rem, 4vw, 2.6rem);
  padding: clamp(2rem, 3.5vw, 2.8rem) clamp(1.6rem, 3vw, 2.6rem);
}
@media (min-width: 54rem) { .about__card { margin-inline: auto; } }
.about__text { font-size: .98rem; max-width: 38rem; }
.about__list {
  list-style: none;
  margin-top: 1.5rem;
  padding-top: 1.2rem;
  border-top: 2px solid var(--aub);
}
.about__list li {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  padding: .5em 0;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--aub-dim);
}
.about__v { color: var(--aub); }

/* ---------- CTA / quote ---------- */

.cta {
  position: relative;
  overflow: hidden;
  padding: clamp(4rem, 10vw, 7rem) var(--pad);
  color: var(--cream);
}
.cta__media { position: absolute; inset: -8% 0; z-index: -2; }
.cta__media img { width: 100%; height: 100%; object-fit: cover; }
.cta__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, var(--cream-deep) 0%, rgba(45,27,46,.9) 16%, rgba(45,27,46,.95) 100%);
}
.cta__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
  max-width: 78rem;
  margin: 0 auto;
}
.cta__copy h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.2rem, 5.2vw, 4rem);
  line-height: 1.02;
  letter-spacing: -.025em;
}
.cta__copy > p { color: rgba(247, 240, 228, .78); max-width: 32rem; margin-top: 1.2rem; }

.cta__routes { display: grid; gap: 1.1rem; margin-top: 2.2rem; }
.route {
  border: 1px solid rgba(247, 240, 228, .18);
  border-left: 3px solid var(--orange);
  border-radius: 0 14px 14px 0;
  padding: 1.3rem 1.4rem;
  background: rgba(247, 240, 228, .05);
  backdrop-filter: blur(6px);
}
.route__num { font-family: var(--font-mono); font-size: .7rem; letter-spacing: .16em; color: var(--orange); }
.route h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.2rem; margin: .3rem 0 .4rem; }
.route p { color: rgba(247, 240, 228, .72); font-size: .93rem; }
.route .btn { margin-top: 1rem; }
.route__arrow { font-size: 1.4rem; color: var(--orange); margin-top: .5rem; animation: nudge 1.8s var(--ease-out) infinite; }
@keyframes nudge { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(5px); } }

.cta__direct { margin-top: 1.8rem; font-size: .94rem; color: rgba(247, 240, 228, .72); }
.cta__direct a { color: var(--orange); }

/* The form is a receipt: paper, aubergine ink, monospace labels. */
.cta__form {
  --tooth: 9px;
  display: grid;
  gap: .85rem;
  padding: clamp(2rem, 3vw, 2.6rem) clamp(1.4rem, 2.5vw, 2.2rem);
  color: var(--aub);
}
.cta__formtitle {
  font-family: var(--font-mono);
  font-size: .82rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  text-align: center;
}
/* The honeypot. Off-canvas rather than display:none, because the bots it is
   for skip fields that are not rendered — the point is that they fill this
   one. Absolutely positioned, so it takes no cell in the two-column grid. */
.cta__form .hp {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
.cta__formsub {
  font-size: .88rem;
  color: var(--aub-dim);
  text-align: center;
  border-bottom: 1.5px dashed var(--aub-faint);
  padding-bottom: 1rem;
  margin-bottom: .3rem;
}
.cta__form label { display: grid; gap: .3rem; }
.cta__form label > span {
  font-family: var(--font-mono);
  font-size: .66rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--aub-dim);
}
.cta__form input,
.cta__form select,
.cta__form textarea {
  font-family: inherit;
  font-size: .95rem;
  color: var(--aub);
  background: rgba(45, 27, 46, .04);
  border: 0;
  border-bottom: 1.5px solid var(--aub-faint);
  border-radius: 0;
  padding: .6em .5em;
  width: 100%;
  transition: border-color .3s, background .3s;
}
.cta__form input:focus,
.cta__form select:focus,
.cta__form textarea:focus {
  outline: none;
  border-color: var(--orange);
  background: rgba(226, 112, 31, .07);
}
.cta__form textarea { resize: vertical; }
.cta__form select { appearance: none; cursor: pointer; }
.cta__form button { margin-top: .6rem; }

.form-status {
  font-family: var(--font-mono);
  font-size: .76rem;
  min-height: 1.2em;
  color: var(--aub-dim);
}
.form-status.is-ok { color: #3f7d4f; }
.form-status.is-err { color: #b4342a; }
.form-legal {
  font-family: var(--font-mono);
  font-size: .64rem;
  letter-spacing: .04em;
  color: rgba(45, 27, 46, .45);
  text-align: center;
}
/* The privacy link inside the fine print. Findable at this size without
   competing with the submit button for attention. */
.form-legal a {
  color: var(--orange-deep);
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
}

/* Two columns of fields once there is room. Full-width rows are named rather
   than counted by position, so reordering fields cannot silently break it. */
@media (min-width: 40rem) {
  .cta__form { grid-template-columns: 1fr 1fr; }
  .cta__formtitle,
  .cta__formsub,
  .cta__form label:has(textarea),
  .cta__form label:has([name="current"]),
  .cta__form button,
  .form-status,
  .form-legal { grid-column: 1 / -1; }
}
@media (max-width: 960px) {
  .cta__inner { grid-template-columns: 1fr; }
}

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

.footer {
  border-top: 1.5px dashed var(--aub-faint);
  padding: 3rem var(--pad) 3.5rem;
  text-align: center;
  background: var(--paper);
}
.footer__brand { font-size: 1.3rem; justify-content: center; color: var(--aub); }
.footer__brand .nav__mark { width: 1.4rem; }
.footer__line { color: var(--aub-dim); margin-top: .9rem; font-size: .94rem; max-width: 46rem; margin-inline: auto; }
.footer__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .6rem 1.4rem;
  margin-top: 1.5rem;
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.footer__nav a { color: var(--aub-dim); text-decoration: none; transition: color .3s; }
.footer__nav a:hover { color: var(--orange-deep); }
.footer__legal {
  color: rgba(45, 27, 46, .45);
  font-size: .78rem;
  margin-top: 1.6rem;
  max-width: 46rem;
  margin-inline: auto;
}


/* ==========================================================================
   Cinematic bands
   A tall section holding a sticky, viewport-filling clip. js/main.js maps
   scroll progress through the section onto the video's currentTime, so the
   picture advances at exactly the rate the visitor scrolls — the "video
   scrubbing" look — and cross-fades the captions at their data-at points.
   ========================================================================== */

.cinema {
  position: relative;
  /* The scroll distance is the timeline. Longer = slower, more deliberate. */
  height: 320vh;
  background: var(--aub);
}
.cinema__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  display: grid;
  place-items: end start;
}
.cinema__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Stock video can look flat; lift it the way a grade would. */
  filter: saturate(1.06) contrast(1.06);
}
.cinema__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(0deg, rgba(45,27,46,.94) 0%, rgba(45,27,46,.5) 45%, rgba(45,27,46,.3) 100%),
    radial-gradient(120% 90% at 50% 50%, transparent 40%, rgba(45,27,46,.75) 100%);
}
/* Seam into the cream page above and below, so the band reads as one film
   rather than a boxed-in video element. */
.cinema::before,
.cinema::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 14vh;
  z-index: 3;
  pointer-events: none;
}
.cinema::before { top: 0; background: linear-gradient(180deg, var(--cream), transparent); }
.cinema--warm::before { background: linear-gradient(180deg, var(--cream-deep), transparent); }
.cinema::after { bottom: 0; background: linear-gradient(0deg, var(--cream), transparent); }
.cinema--warm::after { background: linear-gradient(0deg, var(--cream-deep), transparent); }

.cinema__captions {
  position: relative;
  z-index: 2;
  padding: 0 var(--pad) clamp(4rem, 12vh, 9rem);
  /* Caption and hint stand side by side on the same baseline. The stack keeps
     its own 46rem measure, so putting something next to it does not shorten
     the line length the captions were written to. */
  display: flex;
  align-items: flex-end;
  gap: clamp(1.4rem, 4vw, 3.2rem);
  max-width: 64rem;
}
.cinema__caps { max-width: 46rem; }
/* All captions stack in the same place; only the active one is opaque. */
.cinema__cap {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.7rem, 4.4vw, 3.4rem);
  line-height: 1.1;
  letter-spacing: -.02em;
  color: var(--cream);
  text-wrap: balance;
  opacity: 0;
  transform: translateY(1.4rem);
  transition: opacity .6s var(--ease-out), transform .8s var(--ease-out);
}
.cinema__cap + .cinema__cap { margin-top: -1.15em; }
.cinema__cap.is-live { opacity: 1; transform: none; }
/* The stacked captions overlap, so only the live one may take clicks/AT focus. */
.cinema__cap:not(.is-live) { pointer-events: none; }

/* Film grain. One tiny SVG noise tile, scaled up and drifting — cheaper than a
   canvas and it survives any background underneath. */
.grain {
  position: absolute;
  inset: -50%;
  z-index: 1;
  pointer-events: none;
  opacity: .16;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grainShift 1.1s steps(4) infinite;
}
@keyframes grainShift {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-2%, 1%); }
  50%  { transform: translate(1%, -2%); }
  75%  { transform: translate(-1%, -1%); }
  100% { transform: translate(0, 0); }
}

/* Stills drift inside their frames: the image is taller than the crop so the
   parallax translate has somewhere to go. */
.sit__photo img { height: 112%; }

/* ---- Scroll hint ----
   The band pins itself for three viewport-heights, so a visitor who stops
   reading sees a still frame and one line, with nothing to say that the rest
   of the scene — and the rest of the page — is a scroll away. This is the
   thing that says otherwise, and it sits directly under the caption, where
   the eye already is. A corner is where someone who thinks the page has ended
   never looks, which is the whole failure being fixed.

   It has to hold up over moving film with grain over it, so it is a filled
   disc rather than a hairline outline. */
.scrollhint {
  flex: none;
  display: grid;
  justify-items: center;
  gap: .7rem;
  /* Sits the disc on the same baseline as the caption's last line. */
  margin-bottom: .3rem;
  /* Orange, not cream: the captions are already cream and this has to read as
     an instruction rather than as one more line of the film. It is the site's
     own accent, so it is loud without being foreign. */
  color: var(--orange);
  text-decoration: none;
  cursor: pointer;
  animation: hintBob 1.7s var(--ease-out) infinite;
}
.scrollhint:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: .5rem;
  border-radius: .6rem;
}
.scrollhint__word {
  font-family: var(--font-mono);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: .26em;
  text-transform: uppercase;
  /* letter-spacing hangs off the last letter; pull the word back level. */
  text-indent: .26em;
  white-space: nowrap;
  color: var(--cream);
  text-shadow: 0 1px 12px rgba(45, 27, 46, .9);
}
.scrollhint__arrow {
  position: relative;
  display: grid;
  place-items: center;
  width: 4.1rem;
  height: 4.1rem;
  border: 2.5px solid var(--orange);
  border-radius: 100px;
  background: rgba(45, 27, 46, .55);
  box-shadow: 0 8px 26px rgba(45, 27, 46, .55);
}
.scrollhint__arrow::before {
  content: "";
  width: 1.02rem;
  height: 1.02rem;
  margin-top: -.26rem;
  border-right: 3px solid currentColor;
  border-bottom: 3px solid currentColor;
  transform: rotate(45deg);
}
/* A ring leaving the disc. Peripheral vision is where this has to work — the
   visitor is reading the caption, not looking at the corner of the frame. */
.scrollhint__arrow::after {
  content: "";
  position: absolute;
  inset: -.35rem;
  border: 2px solid var(--orange);
  border-radius: 100px;
  animation: hintHalo 1.7s var(--ease-out) infinite;
}

@keyframes hintBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(.55rem); }
}
@keyframes hintHalo {
  0%        { opacity: .6; transform: scale(1); }
  70%, 100% { opacity: 0;  transform: scale(1.45); }
}

/* Too narrow to stand them side by side — the hint drops under the line. */
@media (max-width: 680px) {
  .cinema__captions { display: block; }
  .scrollhint { justify-items: start; margin-top: clamp(1rem, 3vh, 1.6rem); }
}

@media (prefers-reduced-motion: reduce) {
  /* No pinning, no scrubbing, no grain crawl — just a still frame and its line. */
  .cinema { height: auto; }
  .cinema__sticky { position: static; height: auto; min-height: 70svh; }
  .cinema__cap { opacity: 1; transform: none; }
  .cinema__cap + .cinema__cap { margin-top: .6em; }
  .grain { animation: none; }
  .sit__photo img { height: 100%; }
  /* The band is not pinned here, but there is still page below, so the hint
     stays put — it simply stops moving. */
  .scrollhint { animation: none; }
  .scrollhint__arrow::after { animation: none; opacity: 0; }
}

/* Short viewports (landscape phones) cannot afford 100svh of pinned film. */
@media (max-height: 520px) {
  .cinema { height: 220vh; }
  .cinema__cap { font-size: clamp(1.3rem, 5vw, 2rem); }
}


/* ==========================================================================
   Utilities that arrived with the stage and the FAQ
   ========================================================================== */

/* Visible only to assistive technology. Used for a table header whose meaning
   is carried by a bar rather than by a word. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Skip link. Off-screen until focused, then it lands as a proper button in the
   top-left — above the fixed nav, which is the one thing it has to clear. */
.skip {
  position: fixed;
  top: .75rem; left: .75rem;
  z-index: 200;
  transform: translateY(-160%);
  background: var(--aub);
  color: var(--cream);
  font-family: var(--font-mono);
  font-size: .76rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  padding: .7em 1.2em;
  border-radius: 100px;
  transition: transform .3s var(--ease-out);
}
.skip:focus-visible { transform: none; }

/* Reading progress. A hairline, because the page is long on purpose and the
   only question it answers is how much is left. */
.progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 101;
  height: 2px;
  pointer-events: none;
}
.progress__bar {
  display: block;
  height: 100%;
  background: var(--orange);
  transform: scaleX(0);
  transform-origin: left;
}

/* The nav link for the section you are actually in. Same underline as the hover
   state, so the two can never disagree about what "here" looks like. */
.nav__links a.is-current { opacity: 1; }
.nav__links a.is-current::after { transform: scaleX(1); }


/* ==========================================================================
   The stage — one service, four screens

   A dark bezel set on the cream page, with Odoo inside it. The frame, the tab
   strip and the transport are ours and keep the page's palette; everything
   between them is dressed as the Odoo 20 screen it stands for — the POS floor
   plan, the kitchen display, a product list and the printed Z-report — so this
   section and the four unedited screenshots in section 03 can be held up
   against each other without looking like two different products.

   All of it is CSS. Nothing in here is an image of Odoo, and the line under the
   device says as much; the closer this gets, the more that line is carrying.

   js/stage.js drives it, and what it depends on are the data- attributes in
   index.html, not these class names. Restyle freely.
   ========================================================================== */

.stage {
  padding-block: clamp(4rem, 10vw, 7rem);
  /* The bezel. Local to the device — nothing outside this section should start
     borrowing screen colours for paper. */
  --scr: #1b1019;
  --scr-2: #251729;
  --edge: rgba(247, 240, 228, .13);
  --dim: rgba(247, 240, 228, .58);
  --faint: rgba(247, 240, 228, .34);

  /* Odoo, inside the bezel. Its own small palette, for the same reason. */
  --od-bg: #f8f9fa;
  --od-panel: #fff;
  --od-line: #dee2e6;
  --od-line-soft: #ededf0;
  --od-ink: #1f2937;
  --od-dim: #6b7280;
  --od-primary: #714b67;
  --od-green: #4ea972;
  --od-green-soft: #d3eade;
  --od-green-ink: #16391f;
  --od-blue: #60a8ff;
  --od-blue-soft: rgba(96, 168, 255, .44);
  --od-amber: #d9822b;
  --od-red: #e4575b;
  --od-slate: #5c6670;
  --od-chip: #c8c9cb;
}
.stage[hidden] { display: none; }

.stage__wrap { position: relative; max-width: 78rem; margin: 0 auto; padding: 0 var(--pad); }

/* ---- The rig: three devices on one clock ----
   A phone, a terminal and a tablet, side by side on the paper. The frames are
   ours — dark bezels, a speaker slot, a lens — and everything inside a screen
   is Odoo's. Below 1080px they stack, phone first, because that is where the
   story starts. */

.rig {
  display: grid;
  /* The phone and the tablet give way first, the terminal takes what is left.
     Three abreast holds down to a 125%-zoomed laptop; only a phone stacks. */
  grid-template-columns: minmax(12.5rem, 16rem) minmax(0, 1fr) minmax(15rem, 20rem);
  gap: clamp(.7rem, 1.4vw, 1.4rem);
  align-items: start;
}
@media (max-width: 860px) {
  .rig { grid-template-columns: 1fr; max-width: 40rem; margin-inline: auto; }
}

.dev { margin: 0; min-width: 0; }
.dev__frame {
  position: relative;
  background: var(--scr);
  border: 1px solid var(--edge);
  box-shadow: 0 30px 70px rgba(45, 27, 46, .3), inset 0 2px 0 rgba(255, 255, 255, .06);
}
.dev__screen {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--od-bg);
  color: var(--od-ink);
  font-size: .86rem;
}

/* The phone: tall, rounded, a speaker slot in the bezel above the screen. */
.dev--phone .dev__frame { border-radius: 2.2rem; padding: 1.5rem .55rem .9rem; }
.dev--phone .dev__screen { border-radius: 1.5rem; height: 31rem; font-size: .8rem; }
.dev__speaker {
  position: absolute;
  top: .62rem; left: 50%;
  width: 3.2rem; height: .32rem;
  transform: translateX(-50%);
  border-radius: 100px;
  background: rgba(247, 240, 228, .16);
}

/* The terminal: a wide window with a thin bezel. */
.dev--hq .dev__frame { border-radius: .9rem; padding: .55rem; }
.dev--hq .dev__screen { border-radius: .5rem; height: 31rem; }

/* The tablet: a lens in the bezel, a slightly heavier frame. */
.dev--tablet .dev__frame { border-radius: 1.3rem; padding: 1.1rem .8rem; }
/* The three screens are one fixed height, so a busy kitchen scrolls inside
   its tablet instead of pushing the rig taller. */
.dev--tablet .dev__screen { border-radius: .7rem; height: 31rem; }
/* The tablet is narrower than a real kitchen screen, so its filter bar is set
   a touch tighter to stay on one line. */
.dev--tablet .od__kbar { padding: .45rem .5rem; }
.dev--tablet .od__chip { padding: .35em .5em; font-size: .74rem; gap: .3rem; }
.dev--tablet .od__filters { gap: .1rem; }
.dev__lens {
  position: absolute;
  top: .42rem; left: 50%;
  width: .36rem; height: .36rem;
  transform: translateX(-50%);
  border-radius: 100px;
  background: rgba(247, 240, 228, .22);
}

.dev__cap {
  margin-top: .8rem;
  text-align: center;
  font-size: .78rem;
  color: var(--aub-dim);
}
.dev__cap b {
  display: block;
  font-family: var(--font-mono);
  font-size: .66rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--aub);
  margin-bottom: .15rem;
}

/* The clock, shared by all three. */
.stage__clock,
.stage__covers { display: inline-flex; align-items: baseline; gap: .45rem; color: var(--dim); font-family: var(--font-mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; }
/* Digits must not shuffle the layout as the clock runs. */
.stage__clock b { font-size: 1.05rem; letter-spacing: .06em; color: var(--cream); font-variant-numeric: tabular-nums; }
.stage__covers b { font-size: 1.05rem; color: var(--orange); font-variant-numeric: tabular-nums; }

/* A device shows one view at a time, as Odoo does. */
.pos__view { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: thin; padding: .7rem .8rem .9rem; }
.pos__view[hidden] { display: none; }
.pos__view .bill { border: 0; border-radius: 0; padding: 0; }
.pos__view .pcard { border: 0; margin: 0; padding: 0; background: none; }

/* ---- The phone's own chrome ---- */

.pnav {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .6rem;
  background: var(--od-panel);
  border-bottom: 1px solid var(--od-line);
}
.pnav__back {
  width: 1.9rem; height: 1.9rem;
  flex: none;
  border: 1px solid var(--od-line);
  border-radius: 5px;
  background: var(--od-panel);
  cursor: pointer;
  display: grid;
  place-items: center;
  color: var(--od-ink);
}
.pnav__back[hidden] { display: none; }
.pnav__chev {
  width: .5rem; height: .5rem;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(.08rem, -.08rem);
}
.pnav__title {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  font-size: .86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The floor view on the terminal: the plan runs edge to edge, the legend
   underneath is ours and keeps the padding. */
.pos__view--floor { padding: 0; overflow: hidden; }
.pos__view--floor .legend { padding: .5rem .8rem .7rem; justify-content: flex-start; margin-top: 0; }
.od__btn--sm { padding: .32em .6em; font-size: .72rem; margin-left: auto; }
/* The card's empty state: nothing is open on the phone yet. */
.pcard__empty { color: var(--od-dim); font-size: .78rem; padding: 1.2rem .4rem; text-align: center; }
.pcard__empty[hidden] { display: none; }

/* Odoo's bottom bar on a small screen: two tall buttons, the action and the
   cart with its count. It is the real thing's own layout. */
.switchpane {
  margin-top: auto;
  display: flex;
  gap: .4rem;
  padding: .5rem .55rem;
  background: var(--od-panel);
  border-top: 1px solid var(--od-line);
}
.switchpane[hidden] { display: none; }
.switchpane__btn {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .1rem;
  border: 1px solid var(--od-line);
  border-radius: 6px;
  background: #e9ecef;
  color: var(--od-ink);
  padding: .5em .4em;
  cursor: pointer;
  font: inherit;
  font-size: .78rem;
  font-weight: 600;
  line-height: 1.2;
}
.switchpane__btn small { font-weight: 400; font-size: .68rem; opacity: .85; font-variant-numeric: tabular-nums; }
.switchpane__btn--go { background: var(--od-primary); border-color: var(--od-primary); color: #fff; }
.switchpane__btn--go:disabled {
  background: #e9ecef;
  border-color: var(--od-line);
  color: var(--od-dim);
  cursor: default;
}

/* ---- The terminal's own chrome ---- */

.kpi {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .5rem;
  padding: .7rem .8rem .2rem;
}
.kpi__cell {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--od-line);
  border-radius: 6px;
  background: var(--od-panel);
  padding: .45rem .55rem;
  min-width: 0;
}
/* The amount shrinks before it truncates — a figure cut to "€ 73…" is worse
   than a smaller one. */
.kpi__cell b { font-size: clamp(.86rem, 1.4vw, 1.1rem); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kpi__cell span { font-size: .66rem; line-height: 1.25; color: var(--od-dim); }
.od__seg--hq { padding: .6rem .8rem .2rem; }

/* ==========================================================================
   Odoo chrome

   The furniture every screen shares: the bars along the top of a view, the
   buttons in them, the chips in a kitchen bar. The bezels around the screens
   are ours; everything from here down is dressed as Odoo.
   ========================================================================== */

.od__nav,
.od__kbar,
.od__cp {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .7rem;
  background: var(--od-panel);
  border-bottom: 1px solid var(--od-line);
  font-size: .78rem;
  line-height: 1.2;
}

/* Buttons. Odoo's are square-cornered rectangles with a hairline border; the
   one primary action on a screen is filled. */
.od__btn {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  border: 1px solid var(--od-line);
  border-radius: 5px;
  padding: .42em .7em;
  background: var(--od-panel);
  color: var(--od-ink);
  white-space: nowrap;
}
.od__btn--primary {
  background: var(--od-primary);
  border-color: var(--od-primary);
  color: #fff;
  font-weight: 500;
  padding: .5em 1em;
}
.od__plus { font-size: 1.1em; line-height: 1; }

/* ---- The POS floor screen ---- */

.od__seg { display: inline-flex; }
.od__segbtn {
  border: 1px solid var(--od-line);
  padding: .42em .8em;
  margin-left: -1px;
  background: var(--od-panel);
  color: var(--od-ink);
  cursor: pointer;
  font: inherit;
  transition: background .2s, border-color .2s;
}
.od__segbtn:hover { background: #f3f4f5; }
.od__segbtn:first-child { border-radius: 5px 0 0 5px; margin-left: 0; }
.od__segbtn:last-child { border-radius: 0 5px 5px 0; }
.od__segbtn.is-on {
  background: #e8f1fa;
  border-color: #9cc2e8;
  position: relative;
  z-index: 1;
}
/* The company, where the POS puts its mark. */
.od__mark {
  margin-inline: auto;
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: .01em;
  color: var(--od-primary);
}
.od__navright { display: inline-flex; align-items: center; gap: .7rem; margin-left: auto; }
.od__avatar {
  width: 1.7rem; height: 1.7rem;
  border-radius: 5px;
  background: linear-gradient(140deg, #8d6b84, #4d3348);
}
.od__burger {
  width: 1.1rem; height: .72rem;
  border-top: 2px solid var(--od-ink);
  border-bottom: 2px solid var(--od-ink);
  position: relative;
}
.od__burger::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  margin-top: -1px;
  border-top: 2px solid var(--od-ink);
}
/* The one button in the action bar, and what it is for. */
button.od__btn { cursor: pointer; font: inherit; }
button.od__btn--primary:hover { filter: brightness(1.12); }

/* ---- The order list ---- */

.orders { width: 100%; border-collapse: collapse; font-size: .82rem; }
.orders thead th {
  text-align: left;
  font-size: .74rem;
  font-weight: 600;
  color: var(--od-dim);
  padding: .4rem .5rem;
  border-bottom: 1px solid var(--od-line);
  white-space: nowrap;
}
.orders thead th:last-child { text-align: right; }
.orders__row { border-bottom: 1px solid var(--od-line-soft); }
.orders__row:hover { background: #f6f6f7; }
.orders__row th,
.orders__row td { text-align: left; font-weight: 400; padding: .45rem .5rem; }
.orders__row th { font-variant-numeric: tabular-nums; }
.orders__amt { text-align: right; font-variant-numeric: tabular-nums; }
.orders__st {
  display: inline-block;
  border-radius: 4px;
  padding: .1em .5em;
  background: var(--od-blue-soft);
  font-size: .74rem;
}
.orders__st--paid { background: #d4f2dd; }
/* An order the visitor started themselves, findable in the list. */
.orders__row.is-mine th::after {
  content: "";
  display: inline-block;
  width: .4rem; height: .4rem;
  margin-left: .4rem;
  border-radius: 100px;
  background: var(--od-green);
}

/* The room. Odoo's floor is a plain canvas — the tables are the only thing
   drawn on it, which is why they have to carry their own state. */
/* The floor: a wide canvas, as Odoo's floor screen is, with the plan — the
   box the instance's ten tables sit in, 690 by 530 pixels — centred on it. */
.floor {
  display: flex;
  justify-content: center;
  aspect-ratio: 16 / 9;
  background: var(--od-bg);
}
.floor__plan {
  position: relative;
  height: 100%;
  aspect-ratio: 69 / 53;
}

/* Tables. Buttons, because they are the one thing in the room you can press. */
.tbl {
  position: absolute;
  z-index: 2;
  display: grid;
  place-content: center;
  gap: .05rem;
  border: 2px solid var(--od-green);
  background: var(--od-green-soft);
  color: var(--od-green-ink);
  cursor: pointer;
  font-family: var(--font-body);
  padding: 0;
  transition: background .5s var(--ease-out), border-color .5s, color .5s,
              transform .3s var(--ease-out), box-shadow .3s;
}
.tbl[data-shape="circle"] { border-radius: 50%; }
.tbl[data-shape="oval"]   { border-radius: 100px; }
.tbl[data-shape="square"],
.tbl[data-shape="rect"]   { border-radius: 7px; }

.tbl__n { font-size: clamp(.72rem, 1.5vw, .98rem); font-weight: 700; }
/* The chip Odoo puts on a running table with the order's age on it. It sits
   inside the shape, near the bottom edge, as it does on the real screen —
   which is also why the seat count is not drawn: Odoo does not draw one, and
   the table's accessible name carries it instead. */
.tbl__pill {
  position: absolute;
  left: 50%;
  bottom: -.42rem;
  transform: translateX(-50%);
  border-radius: 100px;
  padding: .05em .4em;
  border: 1px solid rgba(255, 255, 255, .8);
  background: var(--od-green-soft);
  color: var(--od-green-ink);
  font-size: .5rem;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.tbl__pill:empty { display: none; }
.tbl:hover { transform: scale(1.05); }
.tbl.is-picked { box-shadow: 0 0 0 3px rgba(113, 75, 103, .55); }

/* Taken. Odoo fills the shape; the states this page cares about are told apart
   by the chip and the ring, so the floor still reads at a glance as "green is
   busy" the way the real screen does. */
.tbl[data-status="seated"],
.tbl[data-status="fired"],
.tbl[data-status="served"],
.tbl[data-status="bill"] {
  background: var(--od-green);
  border-color: var(--od-green);
  color: #11331d;
}
.tbl[data-status="seated"] .tbl__pill,
.tbl[data-status="served"] .tbl__pill {
  background: rgba(255, 255, 255, .72);
}
/* A ticket in the kitchen is the one state worth catching out of the corner of
   an eye, so it is the only one that moves. */
.tbl[data-status="fired"] .tbl__pill { background: var(--od-amber); color: #fff; }
.tbl[data-status="fired"]::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  border: 2px solid rgba(217, 130, 43, .6);
  animation: firing 1.9s var(--ease-out) infinite;
}
@keyframes firing {
  0%   { opacity: .9; transform: scale(1); }
  70%  { opacity: 0;  transform: scale(1.12); }
  100% { opacity: 0;  transform: scale(1.12); }
}
.tbl[data-status="bill"] { border-color: var(--od-blue); }
.tbl[data-status="bill"] .tbl__pill { background: var(--od-blue); color: #fff; }
.tbl[data-status="paid"] {
  background: #eceff1;
  border-color: #b9c2c8;
  color: #5c6670;
}
.tbl[data-status="paid"] .tbl__pill { background: #d7dde1; color: #5c6670; }

@media (prefers-reduced-motion: reduce) {
  .tbl[data-status="fired"]::after { animation: none; }
  .tbl:hover { transform: none; }
}

/* ---- The order panel beside the floor ---- */

.bill {
  background: var(--od-panel);
  border: 1px solid var(--od-line);
  border-radius: 8px;
  padding: .9rem 1rem 1rem;
  font-size: .85rem;
}
.bill__head { border-bottom: 1px solid var(--od-line); padding-bottom: .55rem; }
.bill__table { font-size: .8rem; color: var(--od-dim); }
.bill__table b { font-size: 1.05rem; color: var(--od-ink); }
.bill__empty { color: var(--od-dim); font-size: .82rem; margin-top: .8rem; }

.bill__list { list-style: none; margin: .5rem 0; }
.bill__list li { position: relative; padding: .4em 0; border-bottom: 1px solid var(--od-line-soft); }
.bill__line { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.bill__name { min-width: 0; }
.bill__amt { flex: none; font-variant-numeric: tabular-nums; }
.bill__unit { display: block; color: var(--od-dim); font-size: .74rem; }

.bill__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
  padding-top: .7rem;
  font-size: .8rem;
  color: var(--od-dim);
}
.bill__total strong {
  font-size: 1.35rem;
  color: var(--od-ink);
  font-variant-numeric: tabular-nums;
}
.bill__btn {
  margin-top: .8rem;
  width: 100%;
  background: var(--od-primary);
  color: #fff;
  border: 0;
  border-radius: 5px;
  padding: .7em 1em;
  cursor: pointer;
  font-family: inherit;
  font-size: .85rem;
  font-weight: 500;
  transition: filter .3s;
}
.bill__btn:hover { filter: brightness(1.12); }
/* A line tapped in and not yet sent: marked, and removable again. */
.bill__list li.is-draft { padding-right: 1.6rem; background: rgba(78, 169, 114, .09); }
.bill__new {
  margin-left: .4rem;
  border-radius: 3px;
  padding: .05em .35em;
  background: var(--od-green);
  color: #fff;
  font-size: .62rem;
  text-transform: lowercase;
  vertical-align: .08em;
}
.bill__rm {
  position: absolute;
  right: 0;
  top: .35em;
  width: 1.3rem; height: 1.3rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--od-line);
  border-radius: 4px;
  background: var(--od-panel);
  color: var(--od-dim);
  cursor: pointer;
  font-family: inherit;
  font-size: .85rem;
  line-height: 1;
}
.bill__rm:hover { border-color: var(--od-red); color: var(--od-red); }

/* ---- The card on the order screen ----
   Odoo's order screen is the order on one side and a grid of product buttons on
   the other. This is that grid, built out of the same menu list as the bill, the
   kitchen tickets, the food cost and the Z-report. */

.pcard {
  border-top: 1px solid var(--od-line);
  padding: .7rem .8rem .8rem;
  background: var(--od-bg);
}
.pcard[hidden] { display: none; }

.pcard__cats { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .55rem; }
.pcard__cat {
  border: 1px solid var(--od-line);
  border-radius: 5px;
  background: var(--od-panel);
  color: var(--od-ink);
  padding: .3em .6em;
  cursor: pointer;
  font-family: inherit;
  font-size: .74rem;
  transition: background .25s, border-color .25s;
}
.pcard__cat:hover { border-color: var(--od-primary); }
.pcard__cat.is-on {
  background: var(--od-primary);
  border-color: var(--od-primary);
  color: #fff;
}
.pcard__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(7.5rem, 100%), 1fr));
  gap: .35rem;
}
.pcard__btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .15rem;
  min-height: 3.4rem;
  border: 1px solid var(--od-line);
  border-radius: 6px;
  background: var(--od-panel);
  color: var(--od-ink);
  padding: .45rem .5rem;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  font-size: .78rem;
  line-height: 1.25;
  transition: border-color .2s, box-shadow .2s, transform .15s var(--ease-out);
}
.pcard__btn[hidden] { display: none; }
.pcard__btn:hover { border-color: var(--od-green); }
.pcard__btn:active { transform: scale(.97); }
.pcard__name { font-weight: 500; }
.pcard__price { color: var(--od-dim); font-size: .74rem; font-variant-numeric: tabular-nums; }
/* 86'd: off the card everywhere at once, which is the whole claim. */
.pcard__btn.is-off {
  background: #f1f2f3;
  color: var(--od-dim);
  cursor: not-allowed;
  text-decoration: line-through;
}
.pcard__btn.is-off:hover { border-color: var(--od-line); }
@media (prefers-reduced-motion: reduce) { .pcard__btn:active { transform: none; } }

/* The split: three payment lines, as the payment screen shows them. */
.bill__split { display: grid; gap: .35rem; margin-top: .8rem; }
.bill__third {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
  border: 1px solid var(--od-line);
  border-left: 3px solid var(--od-green);
  border-radius: 5px;
  padding: .5rem .6rem;
  animation: tearOff .45s var(--ease-out) both;
}
.bill__third:nth-child(2) { animation-delay: .08s; }
.bill__third:nth-child(3) { animation-delay: .16s; }
@keyframes tearOff {
  from { opacity: 0; transform: translateY(-.4rem); }
  to   { opacity: 1; transform: none; }
}
.bill__thirdway { font-size: .78rem; color: var(--od-dim); }
.bill__thirdamt { font-variant-numeric: tabular-nums; font-size: .85rem; }
.bill__hint { font-size: .76rem; color: var(--od-dim); margin-top: .6rem; }
@media (prefers-reduced-motion: reduce) { .bill__third { animation: none; } }

/* The legend is ours, not Odoo's: six states, named, under the rig. */
.legend {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .3rem .9rem;
  margin-top: .9rem;
  font-size: .7rem;
  color: var(--od-dim);
}
.legend li { display: inline-flex; align-items: center; gap: .35rem; }
.legend i {
  width: .65rem; height: .65rem;
  border-radius: 3px;
  border: 2px solid var(--od-green);
  background: var(--od-green-soft);
}
[data-legend="seated"] i,
[data-legend="served"] i { background: var(--od-green); }
[data-legend="fired"] i  { background: var(--od-green); border-color: var(--od-amber); }
[data-legend="bill"] i   { background: var(--od-green); border-color: var(--od-blue); }
[data-legend="paid"] i   { background: #eceff1; border-color: #b9c2c8; }

.od__filters { display: inline-flex; align-items: center; justify-content: center; gap: .2rem; margin-inline: auto; flex-wrap: wrap; }
.od__chip {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  border-radius: 5px;
  padding: .42em .7em;
  white-space: nowrap;
}
.od__chip.is-on { background: rgba(200, 201, 203, .19); border: 1px solid rgba(200, 201, 203, .5); font-weight: 500; }
.od__count {
  border-radius: 4px;
  padding: .05em .4em;
  background: var(--od-chip);
  font-size: .72rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.od__count--blue { background: var(--od-blue-soft); }
.od__count--green { background: rgba(89, 198, 41, .44); }

.pass {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(13rem, 100%), 1fr));
  gap: .7rem;
  align-content: start;
  /* Rows take their content's height and the rail scrolls — without this a
     fixed-height grid shrinks `auto` rows to fit and clips every card. */
  grid-auto-rows: max-content;
  padding: .7rem;
  background: var(--od-bg);
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
}
.pass__quiet { color: var(--od-dim); font-size: .9rem; font-style: italic; }

.tick {
  border: 1px solid var(--od-line);
  border-radius: 6px;
  background: var(--od-panel);
  overflow: hidden;
  /* Set explicitly: `.tick` was once also the pricing section's orange bold
     tick mark, and a page-level rule by that name would bleed in here again. */
  color: var(--od-ink);
  font-weight: 400;
  animation: tickIn .4s var(--ease-out) both;
}
@keyframes tickIn {
  from { opacity: 0; transform: translateY(.5rem) scale(.98); }
  to   { opacity: 1; transform: none; }
}
/* "T10 - C2": the table, and which of its courses this is. */
.tick__head {
  background: #f1f1f1;
  border-bottom: 1px solid var(--od-line);
  padding: .45rem .6rem;
  font-weight: 700;
  font-size: .82rem;
}
.tick__meta { display: flex; align-items: center; gap: .35rem; padding: .5rem .6rem .35rem; }
.tick__state {
  border-radius: 4px;
  padding: .12em .5em;
  background: var(--od-chip);
  font-size: .72rem;
}
.tick[data-stage="ready"] .tick__state { background: var(--od-blue); color: #fff; }
.tick__where {
  border: 1px solid var(--od-line);
  border-radius: 4px;
  padding: .12em .5em;
  font-size: .72rem;
  color: var(--od-dim);
}
/* Age is the whole point of a ticket rail, so it is the one chip that changes
   colour: outlined while the clock is fine, filled red once it is past the
   stage's alert timer — two states, as the real display has. */
.tick__time {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  margin-left: auto;
  border: 1px solid var(--od-line);
  border-radius: 100px;
  padding: .12em .5em;
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
}
.tick__clock {
  width: .62em; height: .62em;
  border: 1.5px solid currentColor;
  border-radius: 50%;
}
.tick[data-age="late"] .tick__time {
  background: var(--od-red);
  border-color: var(--od-red);
  color: #fff;
}
/* The ticket the visitor sent themselves, so it is findable among the
   evening's own without being a different kind of thing. */
.tick.is-mine { border-color: var(--od-green); box-shadow: 0 0 0 2px rgba(78, 169, 114, .22); }
.tick__items { list-style: none; padding: .2rem .6rem .7rem; font-size: .86rem; }
.tick__items li { display: flex; gap: .5rem; padding: .16em 0; }
.tick__q { color: var(--od-dim); flex: none; font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .tick { animation: none; } }

/* ---- The product list ---- */

/* The supplier price is the visitor's hand on the simulation, not a control
   Odoo has — so it keeps the page's paper palette and sits outside the frame. */
.beef {
  display: flex;
  align-items: center;
  gap: .8rem;
  flex-wrap: wrap;
  background: var(--cream-deep);
  border: 1.5px dashed var(--aub-faint);
  border-radius: 100px;
  padding: .55rem 1.1rem;
  margin-bottom: .9rem;
  color: var(--aub);
}
.beef__label {
  font-family: var(--font-mono);
  font-size: .62rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--aub-dim);
}
.beef input[type="range"] { flex: 1; min-width: 8rem; accent-color: var(--orange); }
.beef__out {
  font-family: var(--font-mono);
  font-size: .86rem;
  color: var(--orange-deep);
  min-width: 3.6ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.od__crumb { font-weight: 600; }

.od__pager { color: var(--od-dim); font-size: .74rem; font-variant-numeric: tabular-nums; }

.cost__scroll { overflow-x: auto; }
.cost { width: 100%; border-collapse: collapse; font-size: .85rem; min-width: 30rem; }
.cost thead th {
  text-align: right;
  font-size: .76rem;
  font-weight: 600;
  color: var(--od-dim);
  padding: .6rem .6rem;
  background: var(--od-panel);
  border-bottom: 1px solid var(--od-line);
  white-space: nowrap;
}
.cost thead th:first-child { text-align: left; }
.cost__row { border-bottom: 1px solid var(--od-line-soft); transition: background .4s; }
.cost__row:hover { background: #f6f6f7; }
.cost__dish { text-align: left; font-weight: 400; padding: .55rem .6rem; }
.cost__num,
.cost__pct {
  text-align: right;
  padding: .55rem .6rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cost__pct { font-weight: 600; }
.cost__row[data-state="warn"] .cost__pct { color: #94570f; }
.cost__row[data-state="bad"] .cost__pct { color: #b0282d; }
/* The rows the supplier price actually moved, so the change is findable at a
   glance rather than by comparing two screenshots. */
.cost__row.is-moved { background: rgba(217, 130, 43, .1); }
.cost__row.is-off .cost__dish { text-decoration: line-through; opacity: .45; }

.cost__barcell { padding: .55rem .6rem; width: 26%; }
.cost__bar {
  display: block;
  position: relative;
  height: .5rem;
  border-radius: 100px;
  background: #e9ecef;
}
/* The 35% target, drawn on the track itself — a number is easier to argue with
   when the line it has to beat is right beside it. */
.cost__bar::after {
  content: "";
  position: absolute;
  left: 35%; top: -2px; bottom: -2px;
  width: 1.5px;
  background: rgba(31, 41, 55, .45);
}
.cost__fill {
  display: block;
  height: 100%;
  border-radius: 100px;
  background: var(--od-green);
  transition: width .5s var(--ease-out), background .4s;
}
.cost__row[data-state="warn"] .cost__fill { background: var(--od-amber); }
.cost__row[data-state="bad"] .cost__fill { background: var(--od-red); }

/* Odoo totals the numeric columns under a list. */
.cost__foot th,
.cost__foot td {
  padding: .6rem;
  background: #f3f4f5;
  border-top: 1px solid var(--od-line);
  font-weight: 700;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.cost__foot th { text-align: left; }

.cost__note { color: var(--od-dim); font-size: .74rem; margin-top: .8rem; max-width: 40rem; }

/* ---- The Z-report ----
   A printed document rather than a screen: the slate header and bands are what
   Odoo's report prints, so the sheet is white and sits on the grey. */

.zed {
  max-width: 46rem;
  margin: 0 auto;
  background: #fff;
  border: 1px solid var(--od-line);
  box-shadow: 0 2px 10px rgba(31, 41, 55, .07);
  font-size: .82rem;
}
.zed__top {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 1rem;
  background: var(--od-slate);
  color: #fff;
  padding: 1rem 1.1rem 1.1rem;
}
.zed__co { display: flex; flex-direction: column; font-size: .72rem; color: rgba(255, 255, 255, .72); }
.zed__co b { color: #fff; font-weight: 600; }
.zed__id { text-align: center; font-size: .74rem; color: rgba(255, 255, 255, .8); }
.zed__title {
  font-size: 1.1rem;
  font-weight: 600;
  color: #fff;
  margin-bottom: .3rem;
}
.zed__id span[data-z] { font-variant-numeric: tabular-nums; }

.zed__band {
  background: var(--od-slate);
  color: #fff;
  font-weight: 700;
  font-size: .76rem;
  padding: .3em .8em;
  margin: 1.1rem .9rem .2rem;
}
.zed__tbl { border-collapse: collapse; margin: 0 .9rem; width: calc(100% - 1.8rem); }
.zed__tbl th { text-align: left; font-weight: 400; padding: .35rem .3rem; }
.zed__tbl td {
  text-align: right;
  padding: .35rem .3rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.zed__tbl tbody tr,
.zed__tbl thead tr { border-bottom: 1px solid #e3e3e3; }
.zed__tbl thead th {
  font-size: .68rem;
  color: var(--od-dim);
  text-align: right;
  padding-bottom: .2rem;
}
.zed__cat th,
.zed__cat td { font-weight: 700; }
.zed__item th { padding-left: 1.5rem; }
.zed__sum th,
.zed__sum td {
  font-weight: 700;
  border-top: 1px solid #9aa0a6;
  padding-top: .45rem;
}
.zed__rate {
  display: inline-block;
  min-width: 2.6em;
  font-weight: 600;
}
.zed__tbl--vat th { white-space: nowrap; }

.zed__posted {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  border-top: 1px solid var(--od-line);
  margin: 1.1rem .9rem 0;
  padding: .9rem 0 1.1rem;
  font-size: .8rem;
  color: var(--od-dim);
}
.zed__check {
  position: relative;
  flex: none;
  width: 1.15rem; height: 1.15rem;
  border-radius: 100px;
  border: 1.5px solid var(--od-line);
}
.zed[data-state="posted"] .zed__check { border-color: var(--od-green); background: var(--od-green); }
.zed[data-state="posted"] .zed__check::after {
  content: "";
  position: absolute;
  left: .32rem; top: .2rem;
  width: .28rem; height: .52rem;
  border: solid #fff;
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg);
}
.zed[data-state="posted"] .zed__posted { color: var(--od-ink); }
.zed__done,
.zed[data-state="posted"] .zed__open { display: none; }
.zed[data-state="posted"] .zed__done { display: inline; }

/* ---- The phone, after the real one at phone width ----
   Three icon tabs with the order pill beside them, a grid of table tiles for
   the floor, category chips and card edges in the instance's own colours,
   a receipt grouped by course, and Odoo's control pad under it. */

.pnav__tabs { display: inline-flex; }
.pnav__tab {
  width: 2.3rem; height: 2.1rem;
  margin-left: -1px;
  border: 1px solid var(--od-line);
  background: var(--od-panel);
  color: var(--od-ink);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.pnav__tab:first-child { border-radius: 6px 0 0 6px; margin-left: 0; }
.pnav__tab:last-child { border-radius: 0 6px 6px 0; }
.pnav__tab.is-on { background: #e8f1fa; border-color: #9cc2e8; position: relative; z-index: 1; }
.ico { display: block; width: .95em; height: .95em; border: 1.6px solid currentColor; border-radius: 2px; }
.ico--floor { border-radius: 3px 3px 3px 0; box-shadow: inset -.28em -.28em 0 -.12em currentColor; }
.ico--pen {
  width: .3em; height: 1.05em;
  border: 0;
  border-radius: 2px 2px 1px 1px;
  background: currentColor;
  transform: rotate(45deg);
}
.ico--receipt { border-top-width: 4px; }
.pnav__pill {
  margin-left: .55rem;
  padding: .22em .7em;
  border: 1px solid #9cc2e8;
  border-radius: 100px;
  background: #e8f1fa;
  font-size: .74rem;
  font-weight: 600;
  white-space: nowrap;
  /* The bar is narrow: a pill that cannot shrink pushes the burger off the
     screen and gets cut mid-number. It may shrink, and ends in an ellipsis. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pnav .od__burger { margin-left: auto; }

/* The floor as a grid of tiles. */
.pos__view--grid { padding: .5rem .55rem .8rem; }
.pgrid__bar { margin-bottom: .55rem; }
.pgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: .35rem; }
.pg {
  position: relative;
  aspect-ratio: 1;
  border: 2px solid var(--od-green);
  border-radius: 6px;
  background: var(--od-green-soft);
  color: var(--od-green-ink);
  font: inherit;
  font-weight: 700;
  font-size: .9rem;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.pg[data-status="seated"], .pg[data-status="fired"],
.pg[data-status="served"], .pg[data-status="bill"] { background: var(--od-green); color: #11331d; }
.pg[data-status="paid"] { background: #eceff1; border-color: #b9c2c8; color: #5c6670; }
.pg.is-picked { box-shadow: 0 0 0 3px rgba(113, 75, 103, .55); }
.pg__pill {
  position: absolute;
  left: 50%; bottom: .3rem;
  transform: translateX(-50%);
  border-radius: 100px;
  padding: .05em .45em;
  background: rgba(255, 255, 255, .72);
  font-size: .56rem;
  font-weight: 400;
  white-space: nowrap;
}
.pg__pill:empty { display: none; }

/* The card: chips that scroll sideways, cards with a coloured edge and the
   on-order count in the corner. Colours are the instance's pos_category
   colours (7 teal, 1 red, 5 purple, 0 none), tinted as Odoo tints them. */
.pcard__cats { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; cursor: grab; user-select: none; }
.pcard__cats:active { cursor: grabbing; }
/* A sideways swipe on the card changes category; up and down still scrolls. */
.pcard__grid { touch-action: pan-y; }
.pcard__cat { white-space: nowrap; border-color: transparent; background: #e9ecef; }
.pcard__cat[data-cat="main"],    .pcard__btn[data-cat="main"]    { --cc: #8fdccf; }
.pcard__cat[data-cat="dessert"], .pcard__btn[data-cat="dessert"] { --cc: #f8a7a4; }
.pcard__cat[data-cat="drink"],   .pcard__btn[data-cat="drink"]   { --cc: #cfa8d6; }
.pcard__cat[data-cat="starter"], .pcard__btn[data-cat="starter"] { --cc: #d9dde1; }
.pcard__cat[data-cat] { background: var(--cc); color: var(--od-ink); }
.pcard__cat.is-on { background: var(--cc, var(--od-primary)); color: var(--od-ink); outline: 2px solid var(--od-ink); outline-offset: -2px; }
.pcard__cat[data-cat="all"].is-on { background: var(--od-primary); color: #fff; outline: 0; }
.pcard__btn {
  position: relative;
  min-height: 4.4rem;
  justify-content: center;
  align-items: center;
  text-align: center;
  border-bottom: 4px solid var(--cc, var(--od-line));
}
.pcard__price { display: none; }
.pcard__badge {
  position: absolute;
  right: .3rem; bottom: .35rem;
  min-width: 1.2rem; height: 1.2rem;
  padding: 0 .3rem;
  border-radius: 4px;
  background: #111;
  color: #fff;
  font-size: .7rem;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.pcard__badge:empty { display: none; }

/* The receipt: a bar per course, the kitchen's as sent, the next one green. */
[data-phone-cart] { display: flex; flex-direction: column; }
[data-phone-cart] .bill { display: flex; flex-direction: column; flex: 1; }
.bill__course {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0 -.8rem;
  padding: .35rem .8rem;
  background: #f1f1f1;
  font-size: .8rem;
}
.bill__course.is-new { background: #cfe9d9; }
.bill__sent { border-radius: 4px; padding: .05em .45em; background: #0e9c9c; color: #fff; font-size: .7rem; }
.bill__list li { display: flex; align-items: baseline; gap: .5rem; padding: .4em 0; }
.bill__q { font-weight: 700; min-width: 1ch; }
.bill__name { flex: 1; min-width: 0; }
.bill__amt { font-weight: 600; white-space: nowrap; }
.bill__totals { margin-top: auto; padding-top: .6rem; border-top: 1px solid var(--od-line); }
.bill__vat { display: flex; justify-content: space-between; font-size: .74rem; color: var(--od-dim); }
.bill__total { display: flex; justify-content: space-between; align-items: baseline; padding-top: .1rem; font-size: 1rem; font-weight: 700; color: var(--od-ink); }
.bill__total strong { font-size: 1rem; }

/* Odoo's control pad under the receipt. */
.ctrlpad {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .4rem;
  padding: .5rem .55rem;
  background: var(--od-panel);
  border-top: 1px solid var(--od-line);
}
.ctrlpad[hidden] { display: none; }
.ctrlpad__btn {
  border: 1px solid var(--od-line);
  border-radius: 6px;
  background: #e9ecef;
  color: var(--od-ink);
  padding: .7em .4em;
  font: inherit;
  font-weight: 600;
  font-size: .8rem;
  cursor: pointer;
}
.ctrlpad__btn--pay { background: var(--od-primary); border-color: var(--od-primary); color: #fff; }
.ctrlpad__btn:disabled { opacity: .5; cursor: default; }

/* ---- Transport ---- */

.stage__transport {
  display: flex;
  align-items: center;
  gap: clamp(.7rem, 2vw, 1.2rem);
  flex-wrap: wrap;
  margin-top: 1.3rem;
  padding: .8rem clamp(.9rem, 2vw, 1.4rem);
  background: var(--scr-2);
  border: 1px solid var(--edge);
  border-radius: 16px;
  color: var(--cream);
}
.stage__play {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  flex: none;
  background: var(--orange);
  color: #fff;
  border: 0;
  border-radius: 100px;
  padding: .7em 1.3em;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .66rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: background .3s;
}
.stage__play:hover { background: var(--orange-deep); }
.stage__icon {
  width: .72rem; height: .82rem;
  flex: none;
  background: currentColor;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}
/* Playing: the triangle becomes two bars, drawn with gradients because a
   clip-path cannot cut a hole out of the middle of a shape. */
.stage__play.is-playing .stage__icon {
  clip-path: none;
  background:
    linear-gradient(currentColor 0 0) 0 / 34% 100% no-repeat,
    linear-gradient(currentColor 0 0) 100% / 34% 100% no-repeat;
}
.stage__pausetxt,
.stage__replaytxt { display: none; }
.stage__play.is-playing .stage__playtxt { display: none; }
.stage__play.is-playing .stage__pausetxt { display: inline; }
.stage__play[data-end="1"] .stage__playtxt,
.stage__play[data-end="1"] .stage__pausetxt { display: none; }
.stage__play[data-end="1"] .stage__replaytxt { display: inline; }
.stage__play[data-end="1"] .stage__icon {
  clip-path: polygon(0 0, 100% 50%, 0 100%);
  background: currentColor;
}

.stage__seek { flex: 1; min-width: 9rem; accent-color: var(--orange); cursor: pointer; }

/* ---- Beats ---- */

.toasts {
  position: absolute;
  left: 50%;
  bottom: 8.5rem;
  z-index: 5;
  transform: translateX(-50%);
  width: min(30rem, calc(100% - 2rem));
  display: flex;
  flex-direction: column;
  gap: .4rem;
  pointer-events: none;
}
.toast {
  background: rgba(27, 16, 25, .93);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(226, 112, 31, .45);
  border-left: 3px solid var(--orange);
  border-radius: 4px 12px 12px 4px;
  padding: .7rem .95rem;
  font-size: .82rem;
  color: var(--cream);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .4);
  opacity: 0;
  transform: translateY(.7rem);
  transition: opacity .35s var(--ease-out), transform .45s var(--ease-out);
}
.toast.is-in { opacity: 1; transform: none; }
.toast b { color: var(--orange); font-weight: 600; }
@media (prefers-reduced-motion: reduce) { .toast { transition: opacity .2s; transform: none; } }

/* ---- Under the device ---- */

.stage__disclaim {
  max-width: 46rem;
  margin: 1.4rem auto 0;
  text-align: center;
  font-size: .8rem;
  color: var(--aub-dim);
}
.stage__cta { text-align: center; margin-top: 1.4rem; }

/* Below 640px the floor plan and the cost table are the two things that stop
   fitting: give the plan a squarer crop and let the table scroll. */
@media (max-width: 640px) {

  .od__nav,
  .od__kbar,
  .od__cp { flex-wrap: wrap; font-size: .72rem; }
  .od__mark { order: -1; margin-inline: 0; }
  .zed__top { grid-template-columns: 1fr; }
  .zed__id { text-align: left; }
  .toasts { bottom: 5.4rem; }
}

/* ==========================================================================
   FAQ

   <details>/<summary>, so it opens without JavaScript, is findable with the
   browser's own find-in-page, and announces its own state.
   ========================================================================== */

.faq { padding-block: clamp(4rem, 10vw, 7rem); background: var(--cream-deep); }
.qa { max-width: 54rem; margin: 0 auto; padding: 0 var(--pad); }

.q { border-bottom: 1.5px dashed var(--aub-faint); }
.q:first-child { border-top: 1.5px dashed var(--aub-faint); }
.q summary {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  cursor: pointer;
  list-style: none;
  padding: 1.25rem 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.05rem, 2vw, 1.28rem);
  line-height: 1.3;
  transition: color .3s;
}
.q summary::-webkit-details-marker { display: none; }
.q summary:hover { color: var(--orange-deep); }
/* A plus that becomes a minus. Set in text so it inherits the type size. */
.q summary::after {
  content: "+";
  margin-left: auto;
  flex: none;
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 400;
  color: var(--orange-deep);
  transition: transform .35s var(--ease-out);
}
.q[open] summary::after { content: "\2212"; transform: rotate(180deg); }
.q > p {
  color: var(--aub-dim);
  max-width: 46rem;
  padding: 0 2.5rem 1.5rem 0;
  animation: qOpen .4s var(--ease-out) both;
}
@keyframes qOpen {
  from { opacity: 0; transform: translateY(-.4rem); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .q > p { animation: none; }
  .q[open] summary::after { transform: none; }
}

.qa__more {
  max-width: 54rem;
  margin: 2.2rem auto 0;
  padding: 0 var(--pad);
  font-size: .94rem;
  color: var(--aub-dim);
}
.qa__more a { color: var(--orange-deep); text-underline-offset: .2em; }
