/* e-Καλάθι landing — design tokens from DESIGN.md (mobile/theme) */
:root {
  --cream: #F6F3EE;
  --cream-2: #FBF8F1;
  --cream-3: #F0EADC;
  --surface: #FFFFFF;
  --ink: #163726;
  --ink-2: #44584A;
  --ink-3: #66786B;
  --green: #1E4D33;
  --green-600: #1A4230;
  --green-700: #163726;
  --green-900: #0C2016;
  --green-100: #E3EEDC;
  --green-50: #F2F7EF;
  --leaf: #A5C76E;
  --savings: #4C8C4A;
  --wheat: #F2B233;
  --red: #C43D2B;
  --border: #E7DFCE;
  --border-light: #F0EADC;
  --serif: "Literata", Georgia, "Times New Roman", serif;
  --sans: "Manrope", "Helvetica Neue", Arial, sans-serif;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --gutter: clamp(20px, 5vw, 72px);

  /* The header's veil and the glass pills, as tokens: dark mode has to reach inside them, and they were
     the only brand colours written as literal rgba in places the theme needs to follow. */
  --veil-top: rgba(246,243,238,0.85);
  --veil-bottom: rgba(246,243,238,0);
  --veil-phone: rgba(246,243,238,0.97);
  --glass: rgba(251,248,241,0.58);
  --glass-solid: rgba(251,248,241,0.94);
  --glass-edge: inset 0 0 0 1px rgba(22,55,38,0.08), 0 8px 24px rgba(22,55,38,0.08);
  /* the veil the oil scene lays over its photograph, so the words on it stay legible */
  --oil-wash-1: rgba(246,243,238,0.93); --oil-wash-2: rgba(246,243,238,0.74); --oil-wash-3: rgba(246,243,238,0);
}

/* ---------- Dark ----------
   Not a second palette: the page is already half dark by design — the hero and the shelf are green-900
   scenes with cream type, and every control already knows how to sit on them (.scene--dark, .is-dark).
   Dark mode is that treatment made whole, so the cream scenes take the colours the dark ones already use.
   The photographs stay as they were shot. They are content, not chrome: the oil scene and the finale are
   lit for cream and there is no token that relights them, so instead of washing them out the page keeps
   them and darkens what sits around them.
   JS resolves "auto" and writes the answer here, so one selector covers both; the media query below is
   the no-JS fallback. */
:root[data-scheme="dark"] {
  --cream: #0C2016;                 /* green-900 — the exact background the dark scenes already use */
  --cream-2: #122B1D;               /* raised: chips, glass at rest */
  --cream-3: #193524;               /* sunken: tracks, wells */
  --surface: #16301F;               /* cards that were white */
  --ink: #F6F3EE;
  --ink-2: rgba(246,243,238,0.78);
  --ink-3: rgba(246,243,238,0.56);
  --green-100: #24452F;             /* soft green fills have to darken or they glare */
  --green-50: #17311F;
  --border: #2A4634;
  --border-light: #1E3A27;
  --veil-top: rgba(12,32,22,0.7);
  --veil-bottom: rgba(12,32,22,0);
  --veil-phone: rgba(12,32,22,0.9);
  --glass: rgba(12,32,22,0.42);
  --glass-solid: rgba(12,32,22,0.88);
  --glass-edge: inset 0 0 0 1px rgba(246,243,238,0.12), 0 8px 24px rgba(0,0,0,0.18);
  /* the wash over the family photo has to darken, or cream type lands on a bright shelf */
  --oil-wash-1: rgba(12,32,22,0.92); --oil-wash-2: rgba(12,32,22,0.72); --oil-wash-3: rgba(12,32,22,0);
  /* the cheapest-price green, the promo red and the brand green were picked against cream: on green-900
     they are 2.7:1 as type and as a chip behind dark type, so all three lift */
  --savings: #7FBF6B; --red: #E8705C; --green: #5C9E71; --green-600: #6BAC7E;
  color-scheme: dark;               /* scrollbars and form controls follow */
}

@media (prefers-color-scheme: dark) {
  :root:not([data-scheme]) {
    --cream: #0C2016; --cream-2: #122B1D; --cream-3: #193524; --surface: #16301F;
    --ink: #F6F3EE; --ink-2: rgba(246,243,238,0.78); --ink-3: rgba(246,243,238,0.56);
    --green-100: #24452F; --green-50: #17311F; --border: #2A4634; --border-light: #1E3A27;
    --veil-top: rgba(12,32,22,0.7); --veil-bottom: rgba(12,32,22,0); --veil-phone: rgba(12,32,22,0.9);
    --glass: rgba(12,32,22,0.42); --glass-solid: rgba(12,32,22,0.88);
    --glass-edge: inset 0 0 0 1px rgba(246,243,238,0.12), 0 8px 24px rgba(0,0,0,0.18);
    /* the wash over the family photo has to darken, or cream type lands on a bright shelf */
    --oil-wash-1: rgba(12,32,22,0.92); --oil-wash-2: rgba(12,32,22,0.72); --oil-wash-3: rgba(12,32,22,0);
    /* the cheapest-price green, the promo red and the brand green were picked against cream: on green-900
       they are 2.7:1 as type and as a chip behind dark type, so all three lift */
    --savings: #7FBF6B; --red: #E8705C; --green: #5C9E71; --green-600: #6BAC7E;
    color-scheme: dark;
  }
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: auto; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
.num { font-variant-numeric: tabular-nums; }
.serif { font-family: var(--serif); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- Header ---------- */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--gutter); height: 72px;
  color: var(--ink);
  transition: color 400ms var(--ease-out), background-color 400ms var(--ease-out);
}
.site-header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, var(--veil-top), var(--veil-bottom));
  opacity: 1; transition: opacity 400ms var(--ease-out);
}
.site-header.is-dark { color: var(--cream); }
.site-header.is-dark::before { background: linear-gradient(to bottom, rgba(12,32,22,0.7), rgba(12,32,22,0)); }
.brand { display: flex; align-items: center; gap: 10px; font-family: var(--serif); font-weight: 600; font-size: 24px; letter-spacing: -0.2px; }
.brand img { width: 32px; height: 32px; object-fit: contain; }
/* The mark carries its own cream twin (Iosif, 20/09): on the dark scenes the word "e-καλάθι" already
   turned cream but the basket stayed deep green and sank into the smoky pill. Both files are the same
   drawing at the same 139x140, so this crossfades as a dissolve — nothing shifts. The footer is
   green-900 for good, so there the cream one is simply the one that shows. */
.brand-mark { position: relative; flex: 0 0 32px; width: 32px; height: 32px; }
.brand-mark img { position: absolute; inset: 0; transition: opacity 400ms var(--ease-out); }
.brand-mark .on-dark { opacity: 0; }
.site-header.is-dark .brand-mark img { opacity: 0; }
.site-header.is-dark .brand-mark .on-dark { opacity: 1; }
.site-footer .brand-mark img { opacity: 0; }
.site-footer .brand-mark .on-dark { opacity: 1; }
/* The menu words and the logo sit in frosted glass pills (Iosif, 17/09): over big headings and photos the
   bare words collided with the page. A pill blurs whatever scrolls under it; on dark scenes it turns smoky green. */
.nav-links, .site-header .brand {
  border-radius: 999px; background: var(--glass);
  -webkit-backdrop-filter: blur(18px) saturate(1.6); backdrop-filter: blur(18px) saturate(1.6);
  box-shadow: var(--glass-edge);
  transition: background-color 400ms var(--ease-out), box-shadow 400ms var(--ease-out);
}
.nav-links { display: flex; gap: 6px; font-size: 15px; font-weight: 500; padding: 5px; }
.site-header .brand { padding: 6px 16px 6px 8px; }
.site-header .brand:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.nav-links a { padding: 8px 14px; border-radius: 999px; color: var(--ink-2); transition: color 200ms, background-color 200ms; }
.nav-links a:hover { color: var(--ink); background: rgba(22,55,38,0.07); }
.nav-links a:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.site-header.is-dark .nav-links, .site-header.is-dark .brand { background: rgba(12,32,22,0.42); box-shadow: inset 0 0 0 1px rgba(246,243,238,0.12), 0 8px 24px rgba(0,0,0,0.18); }
.site-header.is-dark .nav-links a { color: rgba(246,243,238,0.86); }
.site-header.is-dark .nav-links a:hover { color: #fff; background: rgba(246,243,238,0.1); }
.site-header.is-dark .nav-links a:focus-visible { outline-color: var(--cream); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav-links, .site-header .brand { background: var(--glass-solid); }
  .site-header.is-dark .nav-links, .site-header.is-dark .brand { background: rgba(12,32,22,0.88); }
}
.cta-pill {
  display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; padding: 11px 18px 11px 14px;
  background: var(--green); color: var(--cream); font-weight: 700; font-size: 14px; border: 0;
  transition: transform 200ms var(--ease-out), background-color 300ms;
}
.cta-pill:hover { transform: translateY(-1px); background: var(--green-600); }
.site-header.is-dark .cta-pill { background: var(--cream); color: var(--ink); }
.site-header.is-dark .cta-pill:hover { background: #fff; }
@media (max-width: 760px) {
  .nav-links { display: none; } .brand { font-size: 21px; } .site-header { height: 64px; }
  /* The phone header has its own dense veil (below), so the logo needs no pill there */
  .site-header .brand, .site-header.is-dark .brand { padding: 0; background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  /* On a phone the headings scroll right under the logo: a denser veil keeps the two from colliding */
  .site-header::before { inset: 0 0 -22px 0; background: linear-gradient(to bottom, var(--veil-phone) 62%, var(--veil-bottom)); }
  .site-header.is-dark::before { background: linear-gradient(to bottom, rgba(12,32,22,0.9) 62%, rgba(12,32,22,0)); }
}
/* The menu needs about 1180px beside the logo and the button. Below that every word wrapped onto two lines
   (iPad upright, phones sideways). The page is one scroll, so narrower screens go without it, like the phone. */
@media (max-width: 1179px) { .nav-links { display: none; } }
.site-header > * { flex-shrink: 0; }
.site-header .brand span, .cta-pill { white-space: nowrap; }

/* ---------- Generic sections ---------- */
.scene { position: relative; width: 100%; }
.scene--dark { background: var(--green-900); color: var(--cream); }
.pin { position: relative; height: 100svh; width: 100%; overflow: hidden; }
.bg { position: absolute; inset: 0; overflow: hidden; }
.bg img, .bg video { width: 100%; height: 100%; object-fit: cover; will-change: transform; }
.h-display { font-family: var(--serif); font-weight: 700; letter-spacing: -0.02em; line-height: 1.0; margin: 0; text-wrap: balance; }
.h-xl { font-size: clamp(48px, 9.5vw, 156px); }
.h-hero { font-size: clamp(42px, 5vw, 74px); line-height: 1.04; }
.nowrap { white-space: nowrap; }
@media (max-width: 760px) { .h-hero { font-size: clamp(38px, 11vw, 46px); } .h-hero .nowrap { white-space: normal; } }
.h-lg { font-size: clamp(40px, 6.5vw, 104px); }
.h-md { font-size: clamp(32px, 4.2vw, 64px); line-height: 1.05; }
.lede { font-size: clamp(17px, 1.6vw, 22px); line-height: 1.5; color: var(--ink-2); max-width: 46ch; text-wrap: pretty; }
.scene--dark .lede { color: rgba(246,243,238,0.82); }
/* Side padding keeps a capital's tonos (Έ, Ό) inside the word's own layer; Safari clips ink outside it */
.w { display: inline-block; will-change: transform, opacity; padding: 0 0.14em; margin: 0 -0.14em; }

/* ---------- Hero: the dark basket video, copy on top ---------- */
.hero .pin { display: grid; grid-template-rows: auto 1fr; }
.hero .bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to right, rgba(12,32,22,0.7), rgba(12,32,22,0.1) 65%); }
.hero-copy { position: relative; z-index: 2; text-align: center; padding: calc(72px + 3vh) var(--gutter) 0; }
.hero-copy .lede { margin: 14px auto 0; text-align: center; font-size: clamp(16px, 1.3vw, 19px); max-width: 60ch; }
.hero-actions { display: flex; justify-content: center; gap: 14px; margin-top: 20px; flex-wrap: wrap; }
.btn {
  display: inline-flex; align-items: center; gap: 10px; border-radius: 16px; padding: 13px 20px 13px 16px;
  font-weight: 800; font-size: 16px; border: 0; transition: transform 200ms var(--ease-out), background-color 300ms;
}
.btn:hover { transform: translateY(-2px); }
.btn--primary { background: var(--green); color: var(--cream); }
.btn--primary:hover { background: var(--green-600); }
.btn--ghost { background: transparent; color: var(--ink); padding-left: 8px; padding-right: 8px; }
.scene--dark .btn--primary { background: var(--cream); color: var(--ink); }
.scene--dark .btn--primary:hover { background: #fff; }
.scene--dark .btn--ghost { color: var(--cream); }
/* Store buttons, one per store: the store's mark, then "Σύντομα στο" / its name.
   Frosted and quiet = not out yet. Solid with depth = live, so the store that is live is always the loud one. */
.stores { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 12px; }
.store {
  display: flex; align-items: center; gap: 12px; min-height: 58px; padding: 9px 24px 9px 18px; border-radius: 16px;
  border: 1px solid transparent; text-align: left; white-space: nowrap;
  transition: transform 260ms var(--ease-out), background-color 300ms, box-shadow 300ms;
}
.store-mark { width: 26px; height: 26px; flex: none; }
.store-text { display: flex; flex-direction: column; gap: 2px; line-height: 1.1; }
.store-k { font-size: 12px; font-weight: 600; letter-spacing: 0.01em; }
.store-n { font-size: 19px; font-weight: 700; letter-spacing: -0.02em; }
.store.is-soon {
  color: var(--ink); cursor: default; border-color: rgba(22,55,38,0.16); background: rgba(255,255,255,0.58);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 1px 2px rgba(22,55,38,0.06);
  -webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4);
}
.store.is-soon .store-k { color: var(--ink-2); }
.store.is-soon .store-mark { opacity: 0.62; }
.store.is-live {
  background: var(--green); color: var(--cream); border-color: rgba(12,32,22,0.5);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 1px 2px rgba(12,32,22,0.3), 0 12px 24px -12px rgba(12,32,22,0.55);
}
.store.is-live .store-k { color: rgba(246,243,238,0.84); }
.store.is-live:hover { transform: translateY(-2px); background: var(--green-600); box-shadow: inset 0 1px 0 rgba(255,255,255,0.16), 0 2px 4px rgba(12,32,22,0.3), 0 18px 30px -14px rgba(12,32,22,0.6); }
.store.is-live:active { transform: translateY(0) scale(0.985); transition-duration: 90ms; }
.store:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
/* Over the hero video: the same frosted glass as the menu, so the label never fights the picture */
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store.is-soon {
  color: var(--cream); border-color: rgba(246,243,238,0.24); background: rgba(12,32,22,0.46);
  box-shadow: inset 0 1px 0 rgba(246,243,238,0.14);
}
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store.is-soon .store-k { color: rgba(246,243,238,0.8); }
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store.is-soon .store-mark { opacity: 0.72; }
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store.is-live { background: var(--cream); color: var(--ink); border-color: rgba(255,255,255,0.7); box-shadow: inset 0 1px 0 #fff, 0 12px 26px -12px rgba(0,0,0,0.6); }
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store.is-live .store-k { color: var(--ink-2); }
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store.is-live:hover { background: #fff; box-shadow: inset 0 1px 0 #fff, 0 18px 32px -14px rgba(0,0,0,0.65); }
:is(.scene--dark, :root[data-scheme="dark"] .finale) .store:focus-visible { outline-color: var(--cream); }
/* Narrow phones: side by side while both fit; when the live label makes one wider, each takes a full row */
@media (max-width: 480px) {
  .stores { display: flex; flex-wrap: wrap; gap: 10px; width: 100%; }
  .store { flex: 1 1 auto; gap: 10px; padding: 9px 16px 9px 14px; }
  .store-mark { width: 22px; height: 22px; }
  .store-n { font-size: 16px; }
}
/* Scroll-scrubbed basket sequence (now in the finale): poster first, canvas takes over */
.seq-visual { position: absolute; inset: 0; }
.seq-visual .seq-poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; object-position: 50% 100%; }
.seq-visual .seq-poster.is-hidden { visibility: hidden; }
canvas.seq { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.hero-copy .lede { margin-top: 16px; }
@media (max-width: 760px) {
  .hero .pin { display: block; }
  /* Copy sits centred at the top of a portrait video: darken from the top down, not from the left */
  .hero .bg::after { background: linear-gradient(to bottom, rgba(12,32,22,0.8), rgba(12,32,22,0.55) 62%, rgba(12,32,22,0.25)); }
  .hero-copy { padding-top: calc(64px + 4vh); }
  .hero-copy .lede { font-size: 16px; }
  .seq-visual { top: 38%; }
  .seq-visual .seq-poster { object-fit: cover; object-position: 72% 100%; }
  .seq-visual::before { content: ""; position: absolute; left: 0; right: 0; top: -2px; height: 34%; z-index: 1; pointer-events: none; background: linear-gradient(to bottom, var(--cream) 4px, rgba(246,243,238,0)); }
}

/* Split hero: copy on the left over the video (desktop only) */
@media (min-width: 761px) {
  .hero--split .pin { display: block; }
  .hero--split .hero-copy { position: absolute; left: var(--gutter); top: 50%; transform: translateY(-54%); width: min(46vw, 660px); padding: 0; text-align: left; }
  .hero--split .h-hero { font-size: clamp(44px, 5.4vw, 84px); }
  .hero--split .hero-copy .lede { margin-left: 0; text-align: left; max-width: 42ch; }
  .hero--split .hero-actions { justify-content: flex-start; }
}

/* ---------- Statement ---------- */
.statement { padding: clamp(96px, 16vh, 200px) var(--gutter); text-align: center; }
.statement .h-display { max-width: 18ch; margin: 0 auto; }
.statement .h-display .w { opacity: 0.18; }
.statement .lede { margin: 28px auto 0; text-align: center; }

/* ---------- Savings: coin stacks + counter ---------- */
.savings {
  --coin-w: clamp(84px, 8.4vw, 148px);
  --coin-step: calc(var(--coin-w) * 0.1);     /* edge thickness of the coin sprite */
  --coin-h: calc(var(--coin-w) * 0.635);      /* sprite aspect 400x254 */
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); align-items: end;
  gap: clamp(32px, 6vw, 96px); max-width: 1180px; margin: clamp(64px, 10vh, 120px) auto 0; text-align: left;
}
/* flex-start, not flex-end: every .coins box is the same height, so aligning the tops puts both stacks on the
   same table even when one caption wraps to more lines than the other */
.stacks { display: flex; justify-content: center; align-items: flex-start; gap: calc(var(--coin-w) * 0.9); }
.stack { margin: 0; position: relative; display: flex; flex-direction: column; align-items: center; width: calc(var(--coin-w) * 1.9); }
.coins { position: relative; width: var(--coin-w); height: calc(var(--coin-step) * 29 + var(--coin-h)); }
/* soft contact shadow on the table */
.coins::before { content: ""; position: absolute; left: -18%; right: -18%; bottom: calc(var(--coin-h) * -0.12); height: calc(var(--coin-h) * 0.55); border-radius: 50%; background: radial-gradient(closest-side, rgba(22,55,38,0.28), rgba(22,55,38,0)); }
.coin { position: absolute; left: 0; width: 100%; height: auto; display: block; will-change: transform, opacity; }
.stack figcaption { margin-top: 22px; text-align: center; display: grid; gap: 4px; }
.stack figcaption b { font-family: var(--serif); font-weight: 700; font-size: clamp(22px, 2vw, 30px); color: var(--ink); letter-spacing: -0.01em; }
.stack figcaption span { font-size: 14px; line-height: 1.35; color: var(--ink-2); max-width: 17ch; }
.stack--dear figcaption b { color: var(--red); }
.stack--smart figcaption b { color: var(--green); }
/* The gap above the smart stack, up to the height of the dear one. Every .coins box is 30 coins tall,
   so the top 6 steps of the box are exactly the 6 coins the smart basket never paid. */
.gap-mark {
  position: absolute; left: calc(50% + var(--coin-w) * 0.62); top: 0;
  height: calc(var(--coin-step) * 6); display: flex; flex-direction: column; justify-content: center; gap: 2px;
  padding-left: 14px; border-left: 2px solid var(--savings); white-space: nowrap; transform-origin: left center;
}
.gap-mark b { font-family: var(--serif); font-weight: 700; font-size: clamp(20px, 1.8vw, 26px); color: var(--savings); line-height: 1; }
.gap-mark span { font-size: 13px; font-weight: 700; color: var(--green); }
.saved { padding-bottom: 8px; }
.saved-value { font-family: var(--serif); font-weight: 700; font-size: clamp(56px, 7vw, 112px); line-height: 1; letter-spacing: -0.02em; color: var(--savings); }
.saved-period { margin-top: 10px; font-size: clamp(17px, 1.5vw, 21px); font-weight: 600; color: var(--ink); }
.saved-steps { list-style: none; display: flex; gap: 8px; padding: 0; margin: 22px 0 0; }
.saved-steps li { font-size: 13px; font-weight: 700; padding: 7px 13px; border-radius: 999px; color: var(--ink-2); background: var(--cream-3); transition: background-color 300ms var(--ease-out), color 300ms var(--ease-out); }
.saved-steps li.is-on { background: var(--green); color: var(--cream); }
.saved-note { margin: 18px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); max-width: 44ch; }
@media (max-width: 900px) {
  .savings { grid-template-columns: 1fr; text-align: center; justify-items: center; }
  .saved-steps { justify-content: center; }
  .saved-note { margin-left: auto; margin-right: auto; }
}
@media (max-width: 760px) {
  .stacks { gap: calc(var(--coin-w) * 0.55); }
  .stack { width: calc(var(--coin-w) * 1.6); }
  /* No room beside the stack on a phone: the label sits centred right above the gap */
  .gap-mark { left: -20%; right: -20%; top: auto; bottom: 100%; height: auto; padding: 0 0 10px; border-left: 0; align-items: center; text-align: center; }
}

/* ---------- Phone scene: steps on the left, the hand rises from the bottom-right edge, the demo plays between ---------- */
.phone-scene .pin { display: block; padding: 0 var(--gutter); }
.phone-steps { position: absolute; left: var(--gutter); top: 50%; width: min(40%, 520px); z-index: 2; }
.step { position: absolute; left: 0; top: 0; transform: translateY(-50%); max-width: 520px; opacity: 0; }
.step[data-index="0"] { opacity: 1; }
.step h3 { font-family: var(--serif); font-weight: 600; font-size: clamp(30px, 3.4vw, 52px); line-height: 1.08; margin: 0 0 14px; letter-spacing: -0.01em; }
.step p { font-size: clamp(16px, 1.4vw, 19px); color: var(--ink-2); margin: 0; max-width: 44ch; }
/* The cut-out photo is 830x1076; the wrist runs off its bottom edge, so the stage sits on the viewport's bottom edge */
/* height capped by width too, so on a narrow-but-tall window the phone never swallows the demo beside it */
.phone-stage { position: absolute; right: 4%; bottom: 0; height: min(90svh, 56vw); aspect-ratio: 830 / 1076; z-index: 1; }
.hand { position: absolute; inset: 0; container-type: size; }
.hand > img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* The photo's own phone spans x 351-765, y 20-829 of the 830x1076 cut-out. The drawn iPhone takes that width,
   sits 16px lower at the bottom and grows upward into empty backdrop, because a real 17 Pro is taller for its
   width (150 x 71.9 mm) than the prop in the photo. Everything below is in units of the phone's width (--pw). */
/* iPhone 18 Pro Max, from Apple's published numbers: body 163.4 x 78.0 mm; 6.9" panel, 2868 x 1320 px at 460 ppi,
   so the glass is 158.4 x 72.9 mm and the border around it 2.5 mm (3.2% of the width). The Dynamic Island shrank
   to about 16.6 mm (21% of the width). Corner radii follow the screen mask Apple ships with the simulator profile. */
.device {
  position: absolute; width: var(--pw); height: calc(var(--pw) / 0.4774);
  border-radius: calc(var(--pw) * 0.164);
  background: linear-gradient(155deg, #3b3e45 0%, #1c1e23 28%, #0c0d10 62%, #17191d 100%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.09), 0 calc(var(--pw) * 0.05) calc(var(--pw) * 0.12) rgba(22,55,38,0.28);
}
.screen {
  position: absolute; inset: calc(var(--pw) * 0.032); border-radius: calc(var(--pw) * 0.132);
  overflow: hidden; background: #000; transform: translateZ(0); /* forces the clip on Safari */
}
/* The one drawn phone is placed twice: over the hand (three screens cross-faded by the scroll) and in each feature card (one still screen) */
.hand .device { --pw: 50cqw; left: 42.3cqw; top: calc(78.5cqh - var(--pw) / 0.4774); }
.hand .screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; }
.hand .screen img[data-index="0"] { opacity: 1; }
.island { position: absolute; left: 50%; top: calc(var(--pw) * 0.055); width: calc(var(--pw) * 0.212); height: calc(var(--pw) * 0.072); transform: translateX(-50%); border-radius: 999px; background: #000; }
.key { position: absolute; width: calc(var(--pw) * 0.014); border-radius: 2px; background: linear-gradient(90deg, #2a2d33, #101216); }
.key--action { left: calc(var(--pw) * -0.012); top: 17.5%; height: 4%; }
.key--up { left: calc(var(--pw) * -0.012); top: 26.5%; height: 7.2%; }
.key--down { left: calc(var(--pw) * -0.012); top: 36%; height: 7.2%; }
.key--side { right: calc(var(--pw) * -0.012); top: 28%; height: 12%; background: linear-gradient(270deg, #2a2d33, #101216); }
.key--camera { right: calc(var(--pw) * -0.012); top: 61%; height: 6%; background: linear-gradient(270deg, #2a2d33, #101216); }
.progress-dots { position: absolute; left: 50%; bottom: 36px; transform: translateX(-50%); display: flex; gap: 8px; z-index: 3; }
.progress-dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--border); transition: background 300ms, transform 300ms; }
.progress-dots i.on { background: var(--green); transform: scale(1.25); }

/* The demo layer: everything here is moved by the scroll timeline; rest positions are set in the pin's own % */
.demo { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
/* .scan and .bcard are zero-size anchors that the timeline moves; the centring transform lives on the body inside,
   so GSAP's own transform never fights it */
.scan { position: absolute; left: 52%; top: 50%; width: 0; height: 0; }
/* explicit width: inside a zero-width anchor, an auto-width image collapses to 0 */
.scan-body { position: absolute; left: 0; top: 0; --scan-h: min(44svh, 30vw); height: var(--scan-h); width: calc(var(--scan-h) * 360 / 811); transform: translate(-50%, -50%); filter: drop-shadow(0 24px 30px rgba(22,55,38,0.22)); }
.scan-body img { width: 100%; height: 100%; display: block; }
.scan-beam { position: absolute; left: -8%; right: -8%; top: 6%; height: 3px; border-radius: 2px; background: #FF3B30; box-shadow: 0 0 14px 4px rgba(255,59,48,0.75); opacity: 0; }
.scan-hit { position: absolute; left: 50%; bottom: -48px; transform: translateX(-50%); background: var(--green); color: var(--cream); font-size: 13px; font-weight: 800; padding: 8px 13px; border-radius: 999px; white-space: nowrap; opacity: 0; }
.ptag {
  position: absolute; display: inline-flex; align-items: center; gap: 10px;
  background: #fff; color: var(--ink); border-radius: 14px; padding: 9px 14px 9px 9px;
  box-shadow: 0 16px 36px rgba(22,55,38,0.14); font-size: 14px; font-weight: 600; white-space: nowrap; opacity: 0; will-change: transform, opacity;
}
.ptag img { width: 40px; height: 26px; object-fit: contain; background: #fff; border-radius: 7px; border: 1px solid var(--border); padding: 2px; }
.ptag .p { font-weight: 800; font-size: 17px; letter-spacing: -0.3px; margin-left: 4px; }
.ptag--best { background: var(--green); color: var(--cream); }
.ptag--best img { border-color: transparent; }
.ptag--worst .p { color: var(--red); }
.ptag[data-i="0"] { left: 45%; top: 20%; }
.ptag[data-i="1"] { left: 54%; top: 30%; }
.ptag[data-i="2"] { left: 44%; top: 40%; }
.ptag[data-i="3"] { left: 53%; top: 50%; }
.ptag[data-i="4"] { left: 44%; top: 60%; }
.ptag[data-i="5"] { left: 54%; top: 70%; }
.bcard { position: absolute; left: 55%; top: 50%; width: 0; height: 0; opacity: 0; will-change: transform, opacity; }
.bcard-body {
  position: absolute; left: 0; top: 0; width: 320px; transform: translate(-50%, -50%);
  background: #fff; color: var(--ink); border-radius: 20px; padding: 16px;
  box-shadow: 0 24px 60px rgba(22,55,38,0.16);
}
.bcard-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.bcard-head b { font-family: var(--serif); font-weight: 700; font-size: 17px; }
.bcard-head small { font-size: 12px; color: var(--ink-2); white-space: nowrap; }
.bcard-row { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 10px; font-size: 14px; font-weight: 600; }
.bcard-row img { width: 34px; height: 22px; object-fit: contain; background: #fff; border-radius: 6px; border: 1px solid var(--border); padding: 2px; }
.bcard-row span { flex: 1; }
.bcard-row b { font-weight: 800; font-size: 15px; letter-spacing: -0.3px; }
.bcard-row.is-best { background: var(--green-50); } .bcard-row.is-best b { color: var(--green); }
.bcard-row.is-worst b { color: var(--red); }
.bcard-foot { margin-top: 8px; padding: 10px 8px 0; border-top: 1px solid var(--border-light); font-size: 12px; color: var(--ink-2); }
.bcard-foot b { color: var(--savings); font-size: 14px; }
@media (min-width: 901px) and (max-width: 1400px) {
  /* narrower desktop: the band between the step text and the phone is ~330px, so the card slims and the right column of tags moves in */
  .bcard { left: 57%; }
  .bcard-body { width: 300px; }
  .ptag[data-i="1"], .ptag[data-i="3"], .ptag[data-i="5"] { left: 52%; }
}
@media (max-width: 900px), (max-width: 1179px) and (orientation: portrait) {
  /* Steps across the top, the hand below them; only three tags and three basket rows fit beside the phone */
  .phone-steps { left: var(--gutter); right: var(--gutter); top: 84px; width: auto; height: 224px; }
  .step { top: 0; transform: none; max-width: none; }
  .step h3 { font-size: 28px; }
  .phone-stage { right: -4%; height: 56svh; }
  .scan { left: 22%; top: 60%; }
  .scan-body { --scan-h: 30svh; }
  .scan-hit { font-size: 12px; bottom: -40px; }
  .ptag { font-size: 12px; gap: 7px; padding: 7px 10px 7px 7px; }
  .ptag img { width: 30px; height: 20px; }
  .ptag .p { font-size: 14px; }
  .ptag--more, .bcard-row--more { display: none; }
  .ptag[data-i="0"] { left: 4%; top: 46%; }
  .ptag[data-i="3"] { left: 4%; top: 55%; }
  .ptag[data-i="5"] { left: 4%; top: 64%; }
  .bcard { left: 30%; top: 58%; }
  .bcard-body { width: 210px; padding: 12px; }
  .bcard-head b { font-size: 15px; }
  .bcard-row { font-size: 12px; padding: 5px 6px; gap: 8px; }
  .bcard-row img { width: 28px; height: 18px; }
  .bcard-row b { font-size: 13px; }
  .progress-dots { left: var(--gutter); transform: none; }
}

/* ---------- Shelf (live) scene ---------- */
.shelf .pin { display: block; }
.shelf .bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(12,32,22,0.8), rgba(12,32,22,0.52) 40%, rgba(12,32,22,0.2) 70%, rgba(12,32,22,0.9)); }
.shelf-copy { position: absolute; left: 0; right: 0; top: calc(72px + 5vh); text-align: center; padding: 0 var(--gutter); z-index: 2; }
.shelf-copy .lede { margin: 16px auto 0; text-align: center; color: var(--cream); text-shadow: 0 1px 14px rgba(12,32,22,0.9), 0 0 2px rgba(12,32,22,0.6); } /* it crosses the bottle and the bread */
.tag {
  position: absolute; z-index: 3; display: inline-flex; align-items: center; gap: 10px;
  background: rgba(246,243,238,0.96); color: var(--ink); border-radius: 14px; padding: 10px 14px 10px 10px;
  box-shadow: 0 18px 40px rgba(0,0,0,0.35); opacity: 0; transform: translateY(18px) scale(0.96);
  font-size: 14px; font-weight: 600; white-space: nowrap;
}
.tag img { width: 40px; height: 26px; object-fit: contain; background: #fff; border-radius: 7px; border: 1px solid var(--border); padding: 2px; }
.tag .p { font-weight: 800; font-size: 17px; letter-spacing: -0.3px; }
.tag--best { background: var(--green); color: var(--cream); }
.tag--best img { border-color: transparent; }
.tag--best .p { color: #fff; }
.tag--worst .p { color: var(--red); }
.live {
  position: absolute; left: 0; right: 0; margin: 0 auto; bottom: 6vh; width: min(92vw, 720px); z-index: 4;
  opacity: 0; transform: translateY(30px);
}
.live form {
  display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.96); color: var(--ink); border-radius: 22px; padding: 8px 8px 8px 20px; height: 68px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.45);
}
.live input { flex: 1; min-width: 0; align-self: stretch; border: 0; outline: 0; background: transparent; font: inherit; font-size: 18px; color: var(--ink); }
.live input::placeholder { color: var(--ink-3); }
.live button { background: var(--green); color: var(--cream); border: 0; border-radius: 15px; height: 52px; padding: 0 22px; font-weight: 800; font-size: 15px; }
.live-chips { display: flex; gap: 8px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }
.live-chips button { background: rgba(246,243,238,0.14); color: var(--cream); border: 1px solid rgba(246,243,238,0.3); border-radius: 999px; padding: 8px 14px; font-size: 14px; font-weight: 600; }
.live-result { margin-top: 14px; background: #fff; color: var(--ink); border-radius: 22px; padding: 16px; box-shadow: 0 30px 80px rgba(0,0,0,0.45); display: none; }
.live-result.is-on { display: block; }
.live-result .head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.live-result .head strong { font-size: 16px; }
.live-result .head small { color: var(--ink-3); font-size: 12px; }
.live-result .row { display: flex; align-items: center; gap: 12px; padding: 9px 10px; border-radius: 12px; }
.live-result .row.best { background: var(--green-50); }
.live-result .row img { width: 40px; height: 26px; object-fit: contain; background: #fff; border-radius: 7px; border: 1px solid var(--border); padding: 2px; }
.live-result .row .n { flex: 1; font-weight: 600; font-size: 14px; }
.live-result .row .v { font-weight: 800; font-size: 16px; letter-spacing: -0.3px; }
.live-result .row.best .v { color: var(--green); }
.live-result .row.worst .v { color: var(--red); }
.live-result .badge { background: var(--green); color: var(--cream); border-radius: 999px; padding: 2px 8px; font-size: 12px; font-weight: 700; }
.live-result .foot { display: flex; justify-content: space-between; margin-top: 8px; padding: 10px 10px 0; border-top: 1px solid var(--border-light); font-size: 12px; color: var(--ink-3); }
.live-result .foot b { color: var(--savings); font-size: 15px; }
@media (max-width: 760px) {
  .shelf .bg::after { background: linear-gradient(to bottom, rgba(12,32,22,0.84), rgba(12,32,22,0.58) 34%, rgba(12,32,22,0.2) 62%, rgba(12,32,22,0.9)); }
  .tag { display: none; } .live form { height: 60px; border-radius: 18px; } .live input { font-size: 16px; }
  /* Anchored to the bottom, eleven chains pushed the search field and the cheapest rows off the top of the phone.
     With a result, hang the block under the header and let the list run downwards instead. */
  .live.has-result { top: 80px; bottom: auto; }
  .live.has-result .live-chips { display: none; }
  .live-result { margin-top: 10px; padding: 12px; }
  .live-result .row { gap: 10px; padding: 4px 8px; }
  .live-result .row img { width: 34px; height: 22px; }
}

/* ---------- Oil scene ---------- */
/* Olive oil, a light scene: a family at the shelf. The subjects fill the middle and right, so the words sit
   top-left over the pale shelves (a cream veil keeps them legible) and the two live prices stack beside the cart. */
.oil { background: var(--cream); color: var(--ink); }
.oil .pin { display: block; }
.oil .bg::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 60% 64% at 0% 14%, rgba(246,243,238,0.93) 0%, rgba(246,243,238,0.74) 46%, rgba(246,243,238,0) 100%); }
.oil-copy { position: absolute; z-index: 2; left: var(--gutter); top: clamp(92px, 13svh, 150px); max-width: min(560px, 40vw); }
.oil-copy .big { font-family: var(--serif); font-weight: 700; font-size: clamp(64px, 9.5vw, 176px); line-height: 0.95; letter-spacing: -0.03em; color: var(--green-700); }
.oil-copy .big small { font-size: 0.32em; font-weight: 600; letter-spacing: 0; vertical-align: 0.9em; margin-left: 0.15em; color: var(--green); }
.oil-copy .range { margin-top: 18px; font-size: clamp(16px, 1.4vw, 21px); line-height: 1.5; color: var(--ink); }
.oil-copy .range b { color: var(--green); font-weight: 800; }
.oil-copy .range [data-oil-min-at], .oil-copy .range [data-oil-max-at] { white-space: nowrap; } /* «στο e-Fresh» never breaks at its hyphen */
.oil-tags { position: absolute; z-index: 2; left: var(--gutter); bottom: clamp(40px, 10svh, 120px); display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.oil-tag { display: inline-flex; align-items: center; gap: 10px; background: rgba(251,248,241,0.97); color: var(--ink); border-radius: 14px; padding: 10px 14px 10px 10px;
  box-shadow: 0 14px 34px rgba(22,55,38,0.22); font-size: 14px; font-weight: 600; white-space: nowrap; }
.oil-tag img { width: 40px; height: 26px; object-fit: contain; background: #fff; border-radius: 7px; border: 1px solid var(--border); padding: 2px; }
.oil-tag .p { font-weight: 800; font-size: 17px; letter-spacing: -0.3px; }
.oil-tag--best { background: var(--green); color: var(--cream); }
.oil-tag--best img { border-color: transparent; }
.oil-tag--best .p { color: #fff; }
.oil-tag--worst .p { color: var(--red); }
@media (max-width: 760px) {
  /* Portrait crops the photo to its middle: keep the girl and the bottle, veil the top for the words. */
  .oil .bg img { object-position: 34% 50%; }
  .oil .bg::after { background: linear-gradient(to bottom, rgba(246,243,238,0.96) 0%, rgba(246,243,238,0.86) 44%, rgba(246,243,238,0) 64%); }
  .oil .pin { display: flex; flex-direction: column; padding: 84px var(--gutter) 0; }
  .oil-copy, .oil-tags { position: relative; left: auto; right: auto; top: auto; bottom: auto; max-width: none; }
  .oil-copy .big { font-size: clamp(64px, 22vw, 104px); }
  .oil-tags { margin-top: 16px; flex-direction: row; flex-wrap: wrap; gap: 8px; }
  .oil-tag { padding: 8px 12px 8px 8px; font-size: 13px; } .oil-tag img { width: 34px; height: 22px; } .oil-tag .p { font-size: 15px; }
}

/* ---------- Weekly basket ---------- */
/* ---- What else it does: a sideways rail, one feature per card, the real screen in a drawn phone ---- */
.extras { background: var(--cream); padding: clamp(96px, 14vh, 180px) 0; overflow: hidden; }
.extras[hidden] { display: none; }
.extras-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; max-width: 1440px; margin: 0 auto clamp(28px, 4vh, 48px); padding: 0 var(--gutter); }
.extras-nav { display: flex; gap: 10px; flex: none; }
.extras-nav button {
  width: 48px; height: 48px; display: grid; place-items: center; border-radius: 999px; color: var(--ink); cursor: pointer;
  border: 1px solid rgba(22,55,38,0.16); background: rgba(255,255,255,0.58); box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 1px 2px rgba(22,55,38,0.06);
  transition: transform 200ms var(--ease-out), opacity 200ms, background-color 300ms;
}
.extras-nav button:hover:not(:disabled) { transform: translateY(-1px); background: #fff; }
.extras-nav button:disabled { opacity: 0.35; cursor: default; }
.extras-nav button:focus-visible, .rail:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.rail {
  display: flex; gap: 20px; margin: 0; padding: 8px var(--gutter) 28px; list-style: none; overflow-x: auto;
  scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); overscroll-behavior-x: contain; scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
/* Pulled with the mouse: the hand cursor says so, and snap steps aside until the release has glided to a card */
@media (hover: hover) and (pointer: fine) { .rail { cursor: grab; } }
.rail.is-dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }
.rail.is-settling { scroll-snap-type: none; }
.rail img { -webkit-user-drag: none; user-select: none; }
/* The rail turns its own pages. Going back to the first card it dims, jumps unseen and returns: eight
   cards spooling backwards in under a second is a blur of phones. */
.rail { transition: opacity 320ms var(--ease-out); }
.rail.is-rewinding { opacity: 0; }
.rail-ctrl { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 0 var(--gutter); color: var(--ink); }
.rail-ctrl[hidden], .rail-play[hidden] { display: none; }
.rail-dots, .rail-play {
  height: 48px; border-radius: 999px; border: 1px solid rgba(22,55,38,0.16); background: rgba(255,255,255,0.58);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 1px 2px rgba(22,55,38,0.06);
}
.rail-dots { display: flex; align-items: center; padding: 0 12px; }
/* The dot is 8px; the button around it is what a finger meets */
.rail-dot { width: 22px; height: 46px; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; display: grid; place-items: center; transition: width 520ms var(--ease-out); }
.rail-dot i {
  position: relative; display: block; width: 8px; height: 8px; border-radius: 999px; overflow: hidden;
  background: rgba(22,55,38,0.5); background: color-mix(in srgb, currentColor 50%, transparent);
  transition: width 520ms var(--ease-out), background-color 300ms;
}
.rail-dot:hover i { background: currentColor; }
.rail-dot.is-active { width: 58px; }
.rail-dot.is-active i { width: 44px; background: rgba(22,55,38,0.22); background: color-mix(in srgb, currentColor 24%, transparent); }
/* The bar is the clock: site.js writes --p from the same counter that turns the page */
.rail-dot.is-active i::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: currentColor; transform-origin: 0 50%; transform: scaleX(var(--p, 0)); }
.rail-ctrl.is-paused .rail-dot.is-active i::after { transform: scaleX(1); }
.rail-play { width: 48px; display: grid; place-items: center; padding: 0; color: inherit; cursor: pointer; transition: transform 200ms var(--ease-out), background-color 300ms; }
.rail-play:hover { transform: translateY(-1px); background: #fff; }
.rail-play .i-play, .rail-ctrl.is-paused .rail-play .i-pause { display: none; }
.rail-ctrl.is-paused .rail-play .i-play { display: block; }
.rail-dot:focus-visible, .rail-play:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; border-radius: 999px; }
@media (prefers-reduced-motion: reduce) { .rail, .rail-dot, .rail-dot i { transition: none; } }
.card {
  position: relative; flex: 0 0 min(980px, 82vw); height: clamp(600px, 78vh, 760px); scroll-snap-align: start;
  display: grid; grid-template-columns: 1.2fr 0.8fr; border-radius: 32px; overflow: hidden;
}
.card-copy { align-self: center; padding: clamp(28px, 4vw, 56px); }
.card-copy h3 { margin: 0; font-family: var(--serif); font-weight: 700; font-size: clamp(28px, 3.1vw, 46px); line-height: 1.06; letter-spacing: -0.02em; text-wrap: balance; }
.card-copy p { margin: 16px 0 0; max-width: 34ch; font-size: clamp(16px, 1.25vw, 19px); line-height: 1.5; }
.card-phone { position: relative; }
/* The page's own drawn iPhone, whole, sized from the space the card gives it (the same container-unit trick as the hand) */
.card-phone { position: relative; container-type: size; }
.card-phone .device { --pw: min(74cqw, calc(86cqh * 0.4774)); left: 50%; top: 50%; transform: translate(-50%, -50%); }
.card-phone .screen { background: var(--cream); }
.card-phone .screen > img { display: block; width: 100%; height: 100%; object-fit: cover; }
.scr-pending { height: 46%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px; padding: 0 12px; color: var(--ink); text-align: center; }
.scr-pending img { width: 44px; height: 44px; }
.scr-pending b { font-family: var(--serif); font-size: 17px; }
.scr-pending span { font-size: 12px; color: var(--ink-2); }
.card--ink { background: var(--green-900); color: var(--cream); }
.card--green { background: var(--green); color: var(--cream); }
.card--ink .card-copy p, .card--green .card-copy p { color: rgba(246,243,238,0.84); }
.card--sand { background: var(--cream-3); color: var(--ink); }
.card--leaf { background: var(--green-100); color: var(--ink); }
.card--paper { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--border); }
.card--sand .card-copy p, .card--leaf .card-copy p, .card--paper .card-copy p { color: var(--ink-2); }
@media (max-width: 760px) {
  .extras-nav { display: none; }
  .rail { gap: 14px; }
  .card { flex-basis: 86vw; height: clamp(640px, 88svh, 760px); grid-template-columns: 1fr; grid-template-rows: auto 1fr; border-radius: 28px; }
  .card-copy { align-self: start; padding: 28px 24px 0; }
  .card-copy p { margin-top: 12px; }
  .card-phone .device { --pw: min(74cqw, calc(92cqh * 0.4774)); }
}
/* Sideways phones: short and wide, so the card keeps two columns and shrinks to the screen */
@media (max-height: 520px) and (orientation: landscape) {
  .extras { padding: 40px 0; }
  .card { flex-basis: min(620px, 78vw); height: 78dvh; grid-template-columns: 1.2fr 0.8fr; grid-template-rows: none; }
  .card-copy { align-self: center; padding: 20px 24px; }
  .card-copy h3 { font-size: clamp(20px, 5.4vh, 26px); }
  .card-copy p { font-size: 14px; margin-top: 8px; }
  .card-phone .device { --pw: min(74cqw, calc(88cqh * 0.4774)); }
}
/* ---------- Chains: every chain we compare, standing still ---------- */
.chains { background: var(--cream); padding: clamp(64px, 10vh, 120px) 0; overflow: hidden; }
.chains h2 { text-align: center; margin: 0 var(--gutter) 28px; }
.chains .sub { text-align: center; color: var(--ink-2); font-size: 14px; margin: -18px 0 28px; }
.logo-wall { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; box-sizing: content-box; max-width: calc(7 * 150px + 6 * 14px); margin: 0 auto; padding: 0 var(--gutter); }
/* The tiles stay white in both themes: every chain mark is drawn for white, and a dark tile would
   turn half of them into mud. On dark they read as paper chips, which is what they are. */
.logo-wall img { height: 64px; width: 150px; object-fit: contain; background: #fff; border: 1px solid var(--border); border-radius: 16px; padding: 14px; }
/* 1180-1250px (iPad sideways, small laptops): seven tiles only fit if they give a little, else 6 + 6 + 1 */
@media (min-width: 1180px) { .logo-wall img { width: min(150px, calc((100% - 6 * 14px) / 7)); } }
@media (max-width: 760px) { .logo-wall { gap: 10px; } .logo-wall img { width: calc((100% - 20px) / 3); height: 52px; padding: 10px; } }

/* ---------- Finale: the cream basket, groceries land as you scroll ---------- */
.finale { background: var(--cream); color: var(--ink); }
.finale .pin { display: flex; align-items: center; padding: 0 var(--gutter); }
.finale-copy { position: relative; z-index: 2; max-width: 680px; }
.finale-copy .lede { margin-top: 18px; }
.finale-actions { display: flex; align-items: center; gap: 18px; margin-top: 30px; flex-wrap: wrap; }
@media (max-width: 760px) {
  .finale .pin { display: block; }
  .finale-copy { padding-top: calc(64px + 4vh); }
  /* The finale copy is taller than the hero's was: start the basket lower so the launch note stays on clear cream */
  .finale .seq-visual { top: 54%; }
}
.site-footer { background: var(--green-900); color: rgba(246,243,238,0.7); padding: 28px var(--gutter); display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; font-size: 13px; }
.site-footer .brand { color: var(--cream); font-size: 18px; }
.site-footer nav { display: flex; flex-wrap: wrap; gap: 10px 20px; }
.site-footer nav a { white-space: nowrap; }

/* ---------- Tablets (761-1179px) ---------- */
@media (min-width: 761px) and (max-width: 1179px) {
  /* five logos a row: 5 + 5 + 3 instead of 4 + 4 + 4 and one alone */
  .logo-wall img { width: calc((100% - 4 * 14px) / 5); }
}
/* Upright, the desktop compositions put the hero's words over the bread and left the finale floating mid-page.
   Upright tablets take the phone's top-down composition, at tablet size. */
@media (min-width: 761px) and (max-width: 1179px) and (orientation: portrait) {
  .hero--split .hero-copy { position: relative; left: auto; top: auto; transform: none; width: auto; padding: calc(72px + 7vh) var(--gutter) 0; text-align: center; }
  .hero--split .h-hero { font-size: clamp(54px, 7.6vw, 84px); }
  .hero--split .hero-copy .lede { margin-left: auto; margin-right: auto; text-align: center; max-width: 48ch; font-size: 19px; }
  .hero--split .hero-actions { justify-content: center; }
  .hero .bg::after { background: linear-gradient(to bottom, rgba(12,32,22,0.82), rgba(12,32,22,0.5) 50%, rgba(12,32,22,0.2)); }
  .phone-steps { top: calc(72px + 4vh); }
  .step h3 { font-size: 36px; }
  /* the basket frame is 1600x899: give it exactly the width's worth of height under the words, no empty band */
  .finale .pin { display: block; height: auto; padding-bottom: calc(100vw * 899 / 1600); }
  .finale-copy { padding-top: 4vh; }
  .finale .seq-visual { top: auto; bottom: 0; height: calc(100vw * 899 / 1600); }
}
/* Wide but short (tablets sideways, small laptops): the lowest row of prices ran into the search bar */
@media (min-width: 761px) and (max-height: 860px) {
  /* top, not translate: GSAP resets the translate property when it animates the tags */
  .tag[data-at="0.30"], .tag[data-at="0.62"] { top: 65% !important; }
  .tag[data-at="0.20"], .tag[data-at="0.51"] { top: 53% !important; } /* the middle row moves up with it, so the rows keep a gap */
}

/* ---------- Notch safe areas ---------- */
/* Sideways, Safari letterboxes a page that does not say viewport-fit=cover: the iPhone's 874px became 756px of
   layout, so the phone's own narrow design showed up on a wide screen. Now the page fills the screen and the
   gutter grows to keep words clear of the camera housing. */
@media (orientation: landscape) {
  :root { --gutter: max(clamp(20px, 5vw, 72px), env(safe-area-inset-left), env(safe-area-inset-right)); }
}
.site-footer { padding-bottom: max(28px, env(safe-area-inset-bottom)); }

/* ---------- Phones held sideways (about 400px tall) ---------- */
/* Headings scale with the height, and the decorations that crowded the copy step aside. */
@media (orientation: landscape) and (max-height: 520px) {
  /* Sideways, Safari hides its bars: 100svh leaves cream bands above and below each scene and lifts the
     search onto the caption. dvh follows the window that is actually there. */
  .pin { height: 100dvh; }
  /* anchored under the header, not centred: with Safari's bar showing there are only ~300px of height */
  .hero--split .hero-copy { top: 60px; transform: none; width: min(62vw, 560px); }
  .hero--split .h-hero { font-size: clamp(24px, 8.5vh, 38px); }
  .hero--split .hero-copy .lede { font-size: 13px; margin-top: 6px; }
  .hero-actions { margin-top: 10px; }
  .btn { padding: 10px 16px; font-size: 14px; min-height: 44px; }
  .store { min-height: 44px; gap: 9px; padding: 4px 16px 4px 12px; border-radius: 14px; }
  .store-mark { width: 20px; height: 20px; }
  .store-text { gap: 0; }
  .store-n { font-size: 14px; }
  .live input { min-height: 44px; }
  .phone-steps { top: calc(50% + 32px); left: var(--gutter); right: auto; width: 50%; height: auto; }
  .step { top: 0; transform: translateY(-50%); }
  .step h3 { font-size: 26px; margin-bottom: 8px; }
  .step p { font-size: 15px; }
  .phone-stage { right: 6%; height: calc(100svh - 64px); }
  .demo { display: none; }
  .progress-dots { bottom: 12px; }
  .shelf-copy { top: 70px; }
  .shelf-copy .h-lg { font-size: clamp(28px, 10vh, 44px); }
  .shelf-copy .lede { font-size: 14px; margin-top: 6px; }
  .tag { display: none; }
  .live { bottom: max(10px, env(safe-area-inset-bottom)); }
  .live form { height: 56px; } .live button { height: 44px; }
  .live.has-result { top: 64px; bottom: auto; }
  .live.has-result .live-chips { display: none; }
  .live-result { max-height: calc(100svh - 140px); overflow: auto; }
  .oil-copy { top: 72px; max-width: 48vw; }
  .oil-copy .big { font-size: clamp(48px, 16vh, 72px); }
  .oil-copy .range { font-size: 14px; margin-top: 6px; }
  .oil-tags { bottom: max(14px, env(safe-area-inset-bottom)); flex-direction: row; gap: 8px; }
  .finale .pin { align-items: flex-end; padding-bottom: max(28px, env(safe-area-inset-bottom)); }
  .finale-copy { max-width: 48vw; }
  .finale-copy .h-lg { font-size: clamp(30px, 10vh, 44px); }
  .finale-copy .lede { font-size: 15px; margin-top: 10px; }
  .finale-actions { margin-top: 14px; }
}

/* ---------- Touch screens: every control at least 44px tall ---------- */
@media (pointer: coarse) {
  .brand, .cta-pill, .live-chips button { min-height: 44px; }
  .nav-links a { padding-top: 12px; padding-bottom: 12px; }
  .site-footer nav { gap: 0 20px; }
  .site-footer nav a { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ---------- Dark: the handful of places a token could not reach ----------
   Everything painted with var(--cream) / var(--ink) / var(--surface) followed the theme on its own.
   What is left are the washes laid over photographs, where the colour is written into a gradient, and
   the header, which in dark mode is over a dark scene at every scroll position rather than some of them. */
.oil .bg::after {
  background: radial-gradient(ellipse 60% 64% at 0% 14%, var(--oil-wash-1) 0%, var(--oil-wash-2) 46%, var(--oil-wash-3) 100%);
}
@media (max-width: 760px) {
  .oil .bg::after { background: linear-gradient(to bottom, var(--oil-wash-1) 0%, var(--oil-wash-2) 44%, var(--oil-wash-3) 64%); }
}
/* Dark mode means every scene is a dark scene, so the mark shows its cream twin from the first pixel
   and the header stops waiting for a scroll trigger to tell it so. */
:root[data-scheme="dark"] .site-header { color: var(--ink); }
:root[data-scheme="dark"] .nav-links a:hover { color: var(--ink); background: rgba(246,243,238,0.1); }
:root[data-scheme="dark"] .brand-mark img { opacity: 0; }
:root[data-scheme="dark"] .brand-mark .on-dark { opacity: 1; }

/* ---------- The places that must NOT follow the theme ----------
   Dark mode flipped --cream and --ink, and that is right for the page. But three kinds of place were
   written against cream from the start and break if the tokens move under them:
     1. the scenes that were ALWAYS dark — the hero, the shelf, the footer, the ink cards. Their type is
        `color: var(--cream)` meaning "the light one", not "the page colour";
     2. the light cards that float on photographs — price tags, the search bar, the phone's cards. The
        photograph underneath does not change, so neither can the card on it;
     3. the store buttons, which come in a light-scene and a dark-scene variant. Which one shows is a
        question about the scene; the colours inside each are not.
   Instead of rewriting every colour inside them, they take the light palette back whole. In light mode
   this block changes nothing — the values are the ones already in :root.
   The finale used to be here too, back when its cream photograph could not follow the theme. It has a
   dark twin now, so it is an ordinary scene again. */
.scene--dark, .site-footer,
.card--ink, .card--green,
.btn--primary, .cta-pill, .store, .live button,
.tag, .ptag, .oil-tag, .bcard-body, .live form, .live-result {
  --cream: #F6F3EE; --cream-2: #FBF8F1; --cream-3: #F0EADC; --surface: #FFFFFF;
  --ink: #163726; --ink-2: #44584A; --ink-3: #66786B;
  --green: #1E4D33; --green-600: #1A4230; --green-700: #163726;
  --green-100: #E3EEDC; --green-50: #F2F7EF;
  --savings: #4C8C4A; --red: #C43D2B;
  --border: #E7DFCE; --border-light: #F0EADC;
}

/* In dark mode every scene is a dark scene, so the header's button is the light pill at every scroll
   position rather than only over the hero and the shelf. */
:root[data-scheme="dark"] .site-header .cta-pill { background: var(--cream); color: var(--ink); }
:root[data-scheme="dark"] .site-header .cta-pill:hover { background: #fff; }

/* The oil headline is deep green on cream by design. On the darkened wash it needs the opposite end of
   the same family, so the two tokens it uses are re-pointed here and nowhere else. */
:root[data-scheme="dark"] .oil-copy { --green-700: #DCE7CB; --green: #9CC97F; }

/* The rail's cards: --green-900 is the page colour in dark, so the ink card would dissolve into it.
   It goes one step deeper than the page, and every card gets a hairline so the rail reads as cards. */
:root[data-scheme="dark"] .card { box-shadow: inset 0 0 0 1px rgba(246,243,238,0.09); }
:root[data-scheme="dark"] .card--ink { background: #061710; }
:root[data-scheme="dark"] .site-footer { border-top: 1px solid rgba(246,243,238,0.1); }

/* The rail's arrows are a white pill with a green hairline; on dark that pill would be a bright hole,
   so it inverts into the same smoky glass the menu uses. */
:root[data-scheme="dark"] :is(.extras-nav button, .rail-dots, .rail-play) {
  border-color: rgba(246,243,238,0.18); background: rgba(246,243,238,0.07);
  box-shadow: inset 0 1px 0 rgba(246,243,238,0.07);
}
:root[data-scheme="dark"] :is(.extras-nav button:hover:not(:disabled), .rail-play:hover) { background: rgba(246,243,238,0.15); }

/* A focus ring is deep green on cream. On dark it all but vanishes, so the controls that sit on the page
   itself take the light end instead. Controls inside a pinned light card keep the green one. */
:root[data-scheme="dark"] :is(.site-header .brand, .nav-links a, .theme-switch, .extras-nav button, .rail, .rail-dot, .rail-play):focus-visible {
  outline-color: #F6F3EE;
}

/* In dark the finale's words sit ON the photograph instead of beside it — the dark basket is composed a
   little further in than the cream one. This is the same veil the hero and the shelf already use for
   exactly this, so the page answers the problem in its own language rather than moving the words.
   Wide screens only: on a phone the copy is stacked ABOVE the image, so there is nothing to veil. */
/* The still shows before the canvas has decoded anything, and it is all there is when the animation
   library does not load. Mirror it the same way, or the basket jumps sideways as the frames arrive. */
@media (min-width: 761px) {
  :root[data-scheme="dark"] .finale .seq-poster { transform: scaleX(-1); }
}
/* The photograph's top edge is a little lighter than the page (studio haze), so wherever that edge shows
   it draws a ruled line: across an upright iPad, under the header of an open foldable, above the basket on
   a phone (all seen 21/09). Every dark finale therefore lets the picture rise out of the page colour, and
   the wide ones add the veil for the words on top of it. --img-top is where the frame is really
   drawn. Wide layouts "contain" the 1600x899 frame and sit it on the floor of a full-width box, so on a wide,
   short screen (an open foldable) its top edge is well below the box's and a fade measured from the box
   fades nothing. Phones "cover" the box, so there it is simply 0. Stylesheet only: the still that shows
   under reduced motion, or before the library loads, is placed the same way and gets the same fade. */
:root[data-scheme="dark"] .finale .seq-visual::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to bottom, rgb(12,32,22) var(--img-top, 0px), rgba(12,32,22,0.7) calc(var(--img-top, 0px) + 12%), rgba(12,32,22,0) calc(var(--img-top, 0px) + 34%));
}
@media (min-width: 761px) {
  .finale .seq-visual { --img-top: max(0px, calc(100% - 100vw * 899 / 1600)); }
  :root[data-scheme="dark"] .finale .seq-visual::after {
    background:
      linear-gradient(to bottom, rgb(12,32,22) var(--img-top, 0px), rgba(12,32,22,0.6) calc(var(--img-top, 0px) + 9%), rgba(12,32,22,0) calc(var(--img-top, 0px) + 24%)),
      linear-gradient(to right, rgba(12,32,22,0.94) 0%, rgba(12,32,22,0.84) 38%, rgba(12,32,22,0.45) 56%, rgba(12,32,22,0) 72%);
  }
}
/* Upright tablets and open foldables stack the words ABOVE the photograph like a phone does, so the veil
   from the left hides nothing that needs hiding: only the rise from the top. */
@media (min-width: 761px) and (max-width: 1179px) and (orientation: portrait) {
  :root[data-scheme="dark"] .finale .seq-visual::after {
    background: linear-gradient(to bottom, rgb(12,32,22) var(--img-top, 0px), rgba(12,32,22,0.7) calc(var(--img-top, 0px) + 12%), rgba(12,32,22,0) calc(var(--img-top, 0px) + 34%));
  }
}

/* ---------- Theme switch ----------
   Three states in one control, because the honest answer to "which theme" is often "the one my phone is
   using". Same glass as the menu so it belongs to the header rather than sitting on top of it. */
.theme-switch {
  position: relative; display: inline-grid; place-items: center; width: 44px; height: 44px; flex: none;
  border: 0; border-radius: 999px; color: inherit; background: var(--glass);
  -webkit-backdrop-filter: blur(18px) saturate(1.6); backdrop-filter: blur(18px) saturate(1.6);
  box-shadow: var(--glass-edge);
  transition: background-color 400ms var(--ease-out), box-shadow 400ms var(--ease-out), transform 200ms var(--ease-out);
}
.theme-switch:hover { transform: translateY(-1px); }
.theme-switch:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.site-header.is-dark .theme-switch { background: rgba(12,32,22,0.42); box-shadow: inset 0 0 0 1px rgba(246,243,238,0.12), 0 8px 24px rgba(0,0,0,0.18); }
.site-header.is-dark .theme-switch:focus-visible { outline-color: #F6F3EE; }
.theme-switch svg { width: 19px; height: 19px; display: block; }
/* one icon per state, only the current one drawn */
.theme-switch [data-icon] { display: none; }
:root:not([data-pref]) .theme-switch [data-icon="auto"],
:root[data-pref="auto"]  .theme-switch [data-icon="auto"],
:root[data-pref="light"] .theme-switch [data-icon="light"],
:root[data-pref="dark"]  .theme-switch [data-icon="dark"] { display: block; }
.site-header > .switch-wrap { display: flex; align-items: center; gap: 10px; }
/* A phone's header now holds three things — the logo, the switch and the button — and together they were
   wider than the screen. Nothing loses its words: the button drops its arrow (the words already say what
   it does), both pills tighten, and the switch keeps a full 44px tap area behind a smaller circle. */
@media (max-width: 480px) {
  .site-header { padding-left: 16px; padding-right: 16px; }
  .site-header > .switch-wrap { gap: 6px; }
  .theme-switch { width: 36px; height: 36px; }
  .theme-switch::after { content: ""; position: absolute; inset: -4px; }
  .theme-switch svg { width: 17px; height: 17px; }
  .cta-pill { padding: 10px 14px; }
  .cta-pill > svg { display: none; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .w, .tag, .oil-tag, .live, .step, .hand .screen img { opacity: 1 !important; transform: none !important; }
  .step { position: relative; top: auto; transform: none; margin-bottom: 40px; }
  .hand .screen img { display: none; } .hand .screen img[data-index="1"] { display: block; }
  /* the light/dark mark still swaps — it just swaps instantly */
  .brand-mark img { transition: none; }
  .demo { display: none; }
}
