/* =========================================================================
   VERSION 3 · "De app"
   Same content and the same signature device as V1 (the live opening-hours
   dial), rebuilt as a native feeling ordering app instead of a marketing
   page. Light app surfaces, platform-first type scale, a five item tab bar,
   a bottom sheet cart. Nothing here shares V1's poster language or V2's
   printed-paper language.

   TOKENS: every text token below was measured against every surface it is
   allowed to land on before a single component used it (LESSONS rule 1).
   The measured ratios are in the comments. Two brand hexes are deliberately
   FILL ONLY, because white or cream on top of them lands at 3.3 to 3.7:1:
     --flame  #f64111  fill only, carries --ink text (4.80:1)
     --leaf   #199b4a  fill only, carries --ink text (4.93:1)
   Their text-safe siblings are --flame-ink and --leaf-ink.
   Everything is scoped to #version-v3 so no token can reach V1 or V2.
   ========================================================================= */

#version-v3 {
  /* surfaces */
  --bg: #f3f5f1;          /* app canvas */
  --card: #ffffff;        /* raised surface */
  --card-2: #e9ede7;      /* inset surface, chips, wells */
  --dark: #0e1b11;        /* device bezel, backdrop, dark bands */
  --dark-2: #16301f;      /* dark band, one step up */

  /* text, with the surfaces each one is cleared for */
  --ink: #0e1b11;         /* card 17.7 · bg 16.2 · card-2 15.0 · flame 4.80 · leaf 4.93 · mustard 9.6 */
  --muted: #4c5a50;       /* card 7.28 · bg 6.63 · card-2 6.15 */
  --cream: #fff3e1;       /* dark 16.2 · dark-2 13.0 · flame-ink 5.00 · leaf-ink 5.55 */
  --cream-dim: #b9b2a3;   /* dark 8.42 · dark-2 6.74 */
  --flame-ink: #c2360f;   /* text on card 5.49 · bg 5.00 — and fill under --cream */
  --leaf-ink: #14713a;    /* text on card 6.08 · bg 5.54 — and fill under #fff */

  /* fills that never carry light text */
  --flame: #f64111;
  --leaf: #199b4a;
  --mustard: #e9b838;

  --line: #dce2d8;
  --line-strong: #c3cdbf;

  /* Platform first: an app should look like it belongs to the OS it runs on,
     so the brand face leads and the real system face catches every fallback. */
  --ui: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;

  --r-card: 20px;
  --r-ctl: 14px;
  --pad: 16px;

  /* Chrome heights. The tab bar is 56px of bar plus the home indicator inset,
     which is what reserves room under the scroller (LESSONS rule 12). */
  --tabbar: 58px;

  --shadow-1: 0 1px 2px rgba(14, 27, 17, 0.06), 0 2px 8px rgba(14, 27, 17, 0.05);
  --shadow-2: 0 6px 22px rgba(14, 27, 17, 0.10);
  --shadow-sheet: 0 -8px 40px rgba(14, 27, 17, 0.28);

  background: var(--dark);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 16px;
  line-height: 1.45;
}

#version-v3 ::selection { background: var(--flame); color: var(--ink); }

/* One focus ring for the whole version, and it is a DOUBLE ring on purpose:
   a single currentColor outline disappears on exactly the filled controls
   that matter most, because there the ring colour is the button's own text
   colour (LESSONS rule 19). Dark core, light halo, so it survives on cream,
   on white and on any filled pill. */
#version-v3 :where(a, button, input, [tabindex]):focus-visible {
  outline: 3px solid var(--dark);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px rgba(255, 243, 225, 0.95);
  border-radius: 8px;
}

/* App rule: no 300ms tap delay, no double tap zoom on controls, no grey
   flash on Android, and chrome text is not selectable the way page copy is.
   Content text stays selectable. */
#version-v3 button,
#version-v3 a,
#version-v3 input,
#version-v3 label {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

#version-v3 .v3-tabbar,
#version-v3 .v3-topbar,
#version-v3 .v3-label,
#version-v3 .v3-tab__label { user-select: none; -webkit-user-select: none; }

/* =========================================================================
   Stage and device
   On a phone the app IS the page, edge to edge. On a desktop it sits in a
   device frame on the brand backdrop, because a full width tab bar on a
   1920px monitor is not what this design is.
   ========================================================================= */

.v3-stage {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 5vw, 72px);
  padding: 40px 24px;
  background:
    radial-gradient(1100px 600px at 78% 8%, rgba(25, 155, 74, 0.16), transparent 60%),
    radial-gradient(900px 520px at 12% 92%, rgba(246, 65, 17, 0.14), transparent 62%),
    var(--dark);
}

.v3-aside {
  width: min(360px, 34vw);
  display: none;
  color: var(--cream);
}

.v3-aside__mark { width: 132px; height: auto; margin-bottom: 22px; }

.v3-aside__title {
  font-size: clamp(28px, 2.4vw, 40px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin-bottom: 14px;
}

.v3-aside__title em { font-style: normal; color: var(--mustard); }

.v3-aside__body { color: var(--cream-dim); font-size: 15px; margin-bottom: 26px; }

.v3-aside__stores { display: flex; flex-wrap: wrap; gap: 10px; }

.v3-storebtn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 8px 16px 8px 13px;
  border: 1px solid rgba(255, 243, 225, 0.34);
  border-radius: 12px;
  color: var(--cream);
  text-decoration: none;
  background: rgba(255, 243, 225, 0.06);
}

.v3-storebtn:active { background: rgba(255, 243, 225, 0.14); }
.v3-storebtn svg { width: 22px; height: 22px; flex: none; }
.v3-storebtn span { display: block; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--cream-dim); }
.v3-storebtn strong { display: block; font-size: 14px; font-weight: 700; }

.v3-device {
  position: relative;
  width: min(390px, 100%);
  height: min(844px, calc(100dvh - 80px));
  flex: none;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-radius: 42px;
  background: var(--bg);
  box-shadow:
    0 0 0 9px #0a1109,
    0 0 0 11px #2b3d31,
    0 44px 90px rgba(0, 0, 0, 0.55);
}

/* =========================================================================
   Top bar · the iOS/Android navigation bar. Title changes per tab.
   ========================================================================= */

.v3-topbar {
  flex: none;
  padding: calc(env(safe-area-inset-top, 0px) + 14px) var(--pad) 10px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
  border-radius: 42px 42px 0 0;
}

.v3-topbar__row { display: flex; align-items: center; gap: 12px; }

.v3-topbar__mark { width: 34px; height: 34px; flex: none; border-radius: 10px; background: var(--dark); padding: 5px; }
.v3-topbar__mark img { width: 100%; height: 100%; object-fit: contain; }

.v3-topbar__title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 44px is Apple's minimum, 48 is Material's. Icon buttons use 44 with a
   48px hit box via padding so both are satisfied. */
.v3-iconbtn {
  position: relative;
  flex: none;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow-1);
  transition: transform 0.12s ease, background 0.15s ease;
}

.v3-iconbtn:active { transform: scale(0.94); background: var(--card-2); }
.v3-iconbtn svg { width: 21px; height: 21px; }

.v3-cartcount {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 21px;
  height: 21px;
  padding: 0 5px;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--flame-ink);
  color: var(--cream);
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
  border: 2px solid var(--card);
}

.v3-cartcount[data-has="1"] { display: inline-flex; }

/* live open/closed strip, filled by script — ships neutral (LESSONS rule 14) */
.v3-status {
  margin-top: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 20px;
  font-size: 12.5px;
  color: var(--muted);
}

.v3-status__dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 999px;
  background: var(--line-strong);
}

.v3-status[data-open="yes"] .v3-status__dot { background: var(--leaf-ink); }
.v3-status[data-open="no"] .v3-status__dot { background: var(--flame-ink); }
.v3-status strong { color: var(--ink); font-weight: 700; }
.v3-status__sep { color: var(--line-strong); }

/* =========================================================================
   Viewport · the one scroller. Everything else is fixed chrome, so there is
   no position:fixed panel anywhere that could cover a primary action.
   ========================================================================= */

.v3-viewport {
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.v3-viewport::-webkit-scrollbar { width: 0; height: 0; }

#v3-main { display: block; }

.v3-screen { padding: 18px var(--pad) 8px; }

/* Without JavaScript every screen simply stacks and the tab bar becomes an
   in page anchor list, so the app degrades to a long single page instead of
   a blank one. The .is-app class only exists once the script has run. */
#version-v3.is-app .v3-screen[data-active="0"] { display: none; }

.v3-screen__head { margin-bottom: 14px; }

.v3-h2 {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.12;
}

.v3-sub { margin-top: 6px; color: var(--muted); font-size: 14px; }

.v3-label {
  display: block;
  margin-bottom: 10px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.v3-block { margin-top: 26px; }

/* =========================================================================
   Buttons
   ========================================================================= */

.v3-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 50px;
  padding: 13px 22px;
  border: 0;
  border-radius: var(--r-ctl);
  background: var(--flame-ink);
  color: var(--cream);
  font-family: var(--ui);
  font-size: 15.5px;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  /* Real resting elevation, the way a filled app button carries it. The
     focus-visible rule above replaces this shadow with the light halo. */
  box-shadow: 0 2px 10px rgba(194, 54, 15, 0.28);
  transition: transform 0.12s ease, filter 0.15s ease;
}

.v3-btn:active { transform: scale(0.975); filter: brightness(0.92); }
.v3-btn svg { width: 18px; height: 18px; flex: none; }
.v3-btn--block { display: flex; width: 100%; }

.v3-btn--ghost {
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-1);   /* neutral, the flame tint belongs to the filled button */
}

.v3-btn--ghost:active { background: var(--card-2); }

.v3-btn--dark { background: var(--dark); color: var(--cream); box-shadow: var(--shadow-2); }

/* =========================================================================
   Home · hero
   The scrim is a background-image on the element that CONTAINS the text, so
   the checker measures real pixels under real type (LESSONS rule 5). The
   bottom stop is near opaque exactly in the band the copy occupies.
   ========================================================================= */

.v3-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 300px;
  padding: 22px 18px 20px;
  border-radius: 24px;
  background-image:
    linear-gradient(to top,
      rgba(10, 20, 12, 0.96) 0%,
      rgba(10, 20, 12, 0.94) 34%,
      rgba(10, 20, 12, 0.72) 56%,
      rgba(10, 20, 12, 0.30) 78%,
      rgba(10, 20, 12, 0.18) 100%),
    url("assets/dish-hero-a.webp");
  background-size: auto, cover;
  background-position: center, center 22%;
  background-repeat: no-repeat;
  color: var(--cream);
}

.v3-hero__tag {
  align-self: flex-start;
  margin-bottom: 12px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--mustard);
  color: var(--ink);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.v3-hero__title {
  font-size: clamp(26px, 7.6vw, 32px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.025em;
}

.v3-hero__title em { font-style: normal; color: var(--mustard); }

.v3-hero__body { margin-top: 10px; font-size: 14.5px; color: var(--cream); }

.v3-hero__actions { margin-top: 16px; display: flex; gap: 10px; }
.v3-hero__actions .v3-btn { flex: 1 1 auto; min-width: 0; }

.v3-hero__actions .v3-btn--ghost {
  background: rgba(255, 243, 225, 0.12);
  color: var(--cream);
  border-color: rgba(255, 243, 225, 0.5);
}

/* quick actions */
.v3-quick { margin-top: 14px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }

.v3-quick__a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 76px;
  padding: 10px 6px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  text-align: center;
  box-shadow: var(--shadow-1);
  min-width: 0;
}

.v3-quick__a:active { background: var(--card-2); }
.v3-quick__a svg { width: 21px; height: 21px; color: var(--flame-ink); }
.v3-quick__a span { font-size: 12px; font-weight: 700; }

/* =========================================================================
   Rails · horizontally scrolling rows. Every rail carries min-width:0 and
   max-width:100% so it can never be the thing that blows the layout out
   sideways (LESSONS rule 10).
   ========================================================================= */

.v3-rail {
  display: flex;
  gap: 10px;
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding: 2px 16px 12px;
  margin: 0 -16px;
  scrollbar-width: none;
}

.v3-rail::-webkit-scrollbar { height: 0; }
.v3-rail > * { scroll-snap-align: start; flex: none; }

.v3-chip {
  width: 116px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 8px 11px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  box-shadow: var(--shadow-1);
}

.v3-chip:active { background: var(--card-2); }

.v3-chip img {
  width: 100%;
  height: 78px;
  object-fit: cover;
  border-radius: 11px;
  background: var(--card-2);
}

.v3-chip span { font-size: 13px; font-weight: 700; line-height: 1.2; }

/* =========================================================================
   Cards
   ========================================================================= */

.v3-card {
  display: block;
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow-1);
  overflow: clip;
  color: var(--ink);
  text-decoration: none;
}

.v3-card__media { display: block; width: 100%; height: 180px; object-fit: cover; background: var(--card-2); }

/* These three are <span> inside an <a> on the Home screen, so they need an
   explicit display. Without it they stay inline, the padding stops holding
   and the name runs into the description on one line. */
.v3-card__body { display: block; padding: 14px 15px 16px; }
.v3-card__name { display: block; font-size: 17px; font-weight: 800; letter-spacing: -0.01em; }
.v3-card__desc { display: block; margin-top: 5px; font-size: 13.5px; color: var(--muted); }

.v3-badge {
  display: inline-block;
  margin-bottom: 8px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--flame);
  color: var(--ink);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.v3-badge--leaf { background: var(--leaf); }
.v3-badge--soft { background: var(--card-2); color: var(--muted); }

.v3-price { margin-top: 11px; display: flex; align-items: baseline; gap: 9px; }
.v3-price__was { font-size: 13.5px; color: var(--muted); }
.v3-price__now { font-size: 21px; font-weight: 800; color: var(--flame-ink); letter-spacing: -0.01em; }

/* =========================================================================
   Deals · add to cart with a stepper
   ========================================================================= */

.v3-deal { margin-bottom: 14px; }
.v3-deal__foot { margin-top: 13px; display: flex; align-items: center; gap: 10px; }

.v3-add {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 46px;
  border: 0;
  border-radius: var(--r-ctl);
  background: var(--flame-ink);
  color: var(--cream);
  font-family: var(--ui);
  font-size: 14.5px;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.12s ease;
}

.v3-add:active { transform: scale(0.975); }

.v3-stepper {
  display: none;
  align-items: center;
  gap: 4px;
  padding: 3px;
  border-radius: var(--r-ctl);
  background: var(--card-2);
}

.v3-deal[data-inbasket="1"] .v3-stepper { display: flex; }
.v3-deal[data-inbasket="1"] .v3-add { display: none; }

.v3-step {
  width: 42px;
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 11px;
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow-1);
}

.v3-step:active { transform: scale(0.92); }
.v3-step svg { width: 17px; height: 17px; }

.v3-qty { min-width: 34px; text-align: center; font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; }

/* =========================================================================
   Kaart · search + list rows
   ========================================================================= */

.v3-search { position: relative; margin-bottom: 16px; }

.v3-search svg {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  color: var(--muted);
  pointer-events: none;
}

.v3-search input {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px 12px 42px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-ctl);
  background: var(--card);
  color: var(--ink);
  font-size: 16px; /* 16px or iOS Safari zooms the page on focus */
}

.v3-search input::placeholder { color: var(--muted); }

.v3-list { display: flex; flex-direction: column; gap: 9px; }

.v3-row {
  display: flex;
  align-items: center;
  gap: 13px;
  min-height: 64px;
  padding: 9px 13px 9px 9px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  box-shadow: var(--shadow-1);
  min-width: 0;
}

.v3-row:active { background: var(--card-2); }
.v3-row img { width: 54px; height: 54px; flex: none; object-fit: cover; border-radius: 12px; background: var(--card-2); }
.v3-row__txt { flex: 1 1 auto; min-width: 0; }
.v3-row__name { display: block; font-size: 15.5px; font-weight: 700; }
.v3-row__meta { display: block; font-size: 12.5px; color: var(--muted); }
.v3-row__go { flex: none; width: 18px; height: 18px; color: var(--muted); }

.v3-empty {
  padding: 30px 20px;
  text-align: center;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-card);
  color: var(--muted);
  font-size: 14px;
}

/* =========================================================================
   Spaar · points
   ========================================================================= */

.v3-points {
  padding: 20px;
  border-radius: var(--r-card);
  background: linear-gradient(150deg, var(--dark-2), var(--dark));
  color: var(--cream);
}

.v3-points__rule { font-size: 13px; color: var(--cream-dim); }
.v3-points__n { margin-top: 4px; font-size: 42px; font-weight: 800; line-height: 1; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
/* The markup carries a real space between the number and the word, so the
   two do not run together for a screen reader. No extra margin on top of it. */
.v3-points__n span { font-size: 16px; font-weight: 700; color: var(--mustard); letter-spacing: 0; }

.v3-slider { margin-top: 18px; }
.v3-slider__top { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; color: var(--cream-dim); margin-bottom: 8px; }
.v3-slider__top b { color: var(--cream); font-size: 15px; font-variant-numeric: tabular-nums; }

.v3-range { width: 100%; height: 34px; background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer; }
.v3-range::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: rgba(255, 243, 225, 0.28); }
.v3-range::-moz-range-track { height: 6px; border-radius: 999px; background: rgba(255, 243, 225, 0.28); }
.v3-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 28px; height: 28px; margin-top: -11px; border-radius: 999px; background: var(--mustard); border: 3px solid var(--dark); }
.v3-range::-moz-range-thumb { width: 28px; height: 28px; border: 3px solid var(--dark); border-radius: 999px; background: var(--mustard); }

.v3-ladder { display: flex; flex-direction: column; gap: 8px; }

.v3-rung {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card);
  min-width: 0;
}

.v3-rung[data-reached="1"] { border-color: var(--leaf-ink); background: #f0f8f2; }

.v3-rung__tick {
  flex: none;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--card-2);
  color: var(--muted);
}

.v3-rung[data-reached="1"] .v3-rung__tick { background: var(--leaf-ink); color: #fff; }
.v3-rung__tick svg { width: 14px; height: 14px; }
.v3-rung__n { flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 600; }
.v3-rung__p { flex: none; font-size: 13px; font-weight: 800; color: var(--muted); font-variant-numeric: tabular-nums; }
.v3-rung[data-reached="1"] .v3-rung__p { color: var(--leaf-ink); }

/* =========================================================================
   Bezoek · the signature dial, at app scale
   ========================================================================= */

.v3-dialwrap { display: flex; justify-content: center; padding: 4px 0 16px; }
.v3-dial { width: min(230px, 62vw); height: auto; }
.v3-dial__track { fill: none; stroke: var(--line-strong); stroke-width: 11; }
.v3-dial__open { fill: none; stroke: var(--leaf-ink); stroke-width: 11; stroke-linecap: round; }
.v3-dial__hand { stroke: var(--flame-ink); stroke-width: 4; stroke-linecap: round; }
.v3-dial__tick { stroke: var(--line-strong); stroke-width: 2; }
.v3-dial__state { fill: var(--ink); font-family: var(--ui); font-size: 17px; font-weight: 800; text-anchor: middle; }
.v3-dial__time { fill: var(--muted); font-family: var(--ui); font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-anchor: middle; }

.v3-days { display: flex; flex-direction: column; gap: 2px; }

.v3-day {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  border-radius: 11px;
  font-size: 14.5px;
  min-width: 0;
}

.v3-day[data-today="1"] { background: var(--card); border: 1px solid var(--line); font-weight: 700; }
.v3-day__n { flex: 1 1 auto; min-width: 0; }
.v3-day__h { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; }
.v3-day[data-today="1"] .v3-day__h { color: var(--ink); }

.v3-contact { display: flex; flex-direction: column; gap: 9px; }

.v3-contact__row {
  display: flex;
  align-items: center;
  gap: 13px;
  min-height: 60px;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  min-width: 0;
}

.v3-contact__row:active { background: var(--card-2); }

.v3-contact__ico {
  flex: none;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  background: var(--card-2);
  color: var(--flame-ink);
}

.v3-contact__ico svg { width: 19px; height: 19px; }
.v3-contact__txt { flex: 1 1 auto; min-width: 0; }
.v3-contact__k { display: block; font-size: 11.5px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.v3-contact__v { display: block; font-size: 15px; font-weight: 700; }

/* =========================================================================
   Reviews
   ========================================================================= */

.v3-score { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.v3-score__n { font-size: 34px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; }
.v3-score__t { font-size: 12.5px; color: var(--muted); }
.v3-stars { display: flex; gap: 2px; color: var(--mustard); }
.v3-stars svg { width: 15px; height: 15px; }

.v3-quote { padding: 15px; border: 1px solid var(--line); border-radius: 16px; background: var(--card); min-width: 0; }
.v3-quote p { margin-top: 9px; font-size: 14px; }
.v3-quote footer { margin-top: 10px; font-size: 12.5px; color: var(--muted); }
.v3-quote cite { font-style: normal; font-weight: 700; color: var(--ink); }

/* =========================================================================
   Footer · sits after </main>, never inside it (LESSONS rule 20)
   ========================================================================= */

.v3-foot {
  margin-top: 18px;
  padding: 18px var(--pad) calc(24px + var(--tabbar) * 0);
  border-top: 1px solid var(--line);
  text-align: center;
  font-size: 12.5px;
  color: var(--muted);
}

.v3-foot p + p { margin-top: 6px; }
.v3-foot a { color: var(--flame-ink); font-weight: 700; }

/* =========================================================================
   Tab bar · 5 items, Apple's 3 to 5 guidance and Material's max of 5.
   58px of bar plus the home indicator inset, and it is a flex sibling of the
   scroller rather than a fixed overlay, so it cannot cover anything.
   ========================================================================= */

.v3-tabbar {
  flex: none;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: stretch;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--card);
  border-top: 1px solid var(--line);
  border-radius: 0 0 42px 42px;
}

.v3-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  min-height: var(--tabbar);
  padding: 7px 2px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-family: var(--ui);
  cursor: pointer;
  text-decoration: none;
  transition: color 0.15s ease;
}

.v3-tab svg { width: 22px; height: 22px; flex: none; }

.v3-tab__label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.v3-tab[aria-current="page"] { color: var(--flame-ink); }
.v3-tab:active { background: var(--card-2); }

/* =========================================================================
   Cart sheet · a real modal bottom sheet, scoped to the device
   ========================================================================= */

/* An author `display` beats the UA rule for the hidden attribute, so without
   these two the closed sheet stays laid out at translateY(102%), hangs below
   the device and makes the whole document scrollable. That is what put empty
   background under the app on a cold load. */
#version-v3 .v3-scrim[hidden],
#version-v3 .v3-sheet[hidden] { display: none; }

.v3-scrim {
  position: absolute;
  inset: 0;
  z-index: 40;
  background: rgba(10, 20, 12, 0.5);
  border-radius: 42px;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease, visibility 0.2s ease;
}

#version-v3[data-sheet="open"] .v3-scrim { opacity: 1; visibility: visible; }

.v3-sheet {
  position: absolute;
  z-index: 41;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 82%;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  border-radius: 26px 26px 42px 42px;
  background: var(--bg);
  box-shadow: var(--shadow-sheet);
  transform: translateY(102%);
  visibility: hidden;
  transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1), visibility 0.28s;
}

#version-v3[data-sheet="open"] .v3-sheet { transform: translateY(0); visibility: visible; }

.v3-sheet__grip { flex: none; width: 40px; height: 4px; margin: 9px auto 2px; border-radius: 999px; background: var(--line-strong); }

.v3-sheet__head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px var(--pad) 12px;
  border-bottom: 1px solid var(--line);
}

.v3-sheet__title { flex: 1 1 auto; min-width: 0; font-size: 18px; font-weight: 800; }

.v3-sheet__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 14px var(--pad);
}

.v3-sheet__foot {
  flex: none;
  padding: 13px var(--pad) 18px;
  border-top: 1px solid var(--line);
  background: var(--card);
  border-radius: 0 0 42px 42px;
}

.v3-total { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 11px; }
.v3-total span { font-size: 14px; color: var(--muted); }
.v3-total b { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; }

.v3-bi { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--line); min-width: 0; }
.v3-bi:last-child { border-bottom: 0; }
.v3-bi img { width: 52px; height: 52px; flex: none; object-fit: cover; border-radius: 12px; background: var(--card-2); }
.v3-bi__txt { flex: 1 1 auto; min-width: 0; }
.v3-bi__n { display: block; font-size: 14.5px; font-weight: 700; }
.v3-bi__p { display: block; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.v3-bi .v3-stepper { display: flex; flex: none; }
.v3-bi .v3-step { width: 36px; height: 36px; }
.v3-bi .v3-qty { min-width: 26px; font-size: 15px; }

.v3-note { margin-top: 10px; font-size: 12px; color: var(--muted); text-align: center; }

/* =========================================================================
   Breakpoints
   ========================================================================= */

/* Room for the explanatory column only once the phone is not already the
   whole story. */
@media (min-width: 1100px) {
  .v3-aside { display: block; }
}

/* Phone: the app becomes the page. No bezel, no backdrop, edge to edge, and
   the safe area insets start doing real work. */
@media (max-width: 759px) {
  .v3-stage { padding: 0; background: var(--bg); display: block; }
  .v3-device {
    width: 100%;
    height: 100dvh;
    border-radius: 0;
    box-shadow: none;
  }
  .v3-topbar,
  .v3-tabbar,
  .v3-sheet,
  .v3-sheet__foot,
  .v3-scrim { border-radius: 0; }
  .v3-sheet { border-radius: 22px 22px 0 0; }
}

/* Short landscape phones: give the scroller the room back. */
@media (max-height: 520px) and (max-width: 959px) {
  .v3-status { display: none; }
  .v3-topbar { padding-top: calc(env(safe-area-inset-top, 0px) + 8px); padding-bottom: 8px; }
  #version-v3 { --tabbar: 48px; }
  .v3-tab__label { display: none; }
  .v3-tab { gap: 0; }
}

/* Motion. shell.css already flattens durations under reduced motion; this
   makes the intent explicit for the sheet, which is the only real transition
   in this version. V3 uses no scroll triggered reveals at all, so there is
   nothing here that can be left permanently invisible. */
@media (prefers-reduced-motion: reduce) {
  #version-v3 .v3-sheet { transition: visibility 0.001ms; }
  #version-v3 .v3-viewport { scroll-behavior: auto; }
}
