/* =====================================================================
   nv-card — the two-sided digital business card
   =====================================================================

   REQUIRES app/css/nv-base.css, loaded before this file. The palette, the
   geometry tokens, `.nv-body` and the `.nv-sheet` surface live there and are
   shared with the menu page.

   Deliberately NOT written in Tailwind utilities. Two reasons:

   1. Editing this file never requires a Tailwind rebuild. A card design
      that can only be changed by re-running the build is a design nobody
      changes.
   2. Per-business customisation (CardCustomization.css_file) can restyle
      the whole card by overriding CUSTOM PROPERTIES, without having to
      out-specify a wall of utility classes.

   ---------------------------------------------------------------------
   STRUCTURE
   ---------------------------------------------------------------------
   .nv-stage                 viewport, centres the card
     .nv-card                the token scope + perspective
       .nv-card__inner       the element that actually rotates
         .nv-face--front     gallery, identity, calls to action
         .nv-face--back      the information side
   ===================================================================== */

/* ── stage ──────────────────────────────────────────────────────────── */

.nv-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* A DEFINITE height, not min-height. The card sizes itself with
     `height: 100%`, and a percentage height cannot resolve against a parent
     whose only vertical constraint is a minimum — the whole card collapsed
     to zero and its contents spilled out of an unclickable box. --vh is the
     fallback for browsers that never shipped dynamic viewport units. */
  height: calc(var(--vh, 1vh) * 100);
  height: 100dvh;
  padding: max(env(safe-area-inset-top), 10px) 10px max(env(safe-area-inset-bottom), 10px);
  box-sizing: border-box;
  isolation: isolate;
  /* Clips the decorative glow below, whose negative inset would otherwise
     add ~80px of scrollable width to the document. */
  overflow: hidden;
}

/* An out-of-focus wash of the business's own colours behind the card, so
   the page is not a flat rectangle on desktop. Purely decorative. */
.nv-stage::before {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: -1;
  /* No filter: blur(). A radial gradient is already soft, and blurring one
     across a box inset 20% beyond the viewport made the browser allocate and
     re-filter a layer larger than the screen — permanently, and on every
     frame of anything composited above it. Wider, softer stops give the same
     look for nothing. */
  background:
    radial-gradient(55% 50% at 30% 18%, var(--nv-stage-glow), transparent 72%),
    radial-gradient(50% 55% at 74% 82%, var(--nv-stage-glow), transparent 72%);
  pointer-events: none;
}

/* ── card + flip ────────────────────────────────────────────────────── */

.nv-card {
  position: relative;
  width: 100%;
  max-width: var(--nv-max-w);
  height: 100%;
  max-height: var(--nv-max-h);
  min-height: 0;
  perspective: 1800px;
  box-sizing: border-box;
  /* The lift lives here, as a scale — see the keyframe below. The transition
     is for the DRAG, which holds the dip for as long as the finger is down
     and needs it to ease in and out rather than snap. */
  transition: transform 200ms var(--nv-ease-soft);
}

@media (min-width: 480px) and (min-height: 620px) {
  .nv-card {
    /* Once there is room, hold real card proportions instead of stretching
       to the viewport — this is the difference between "a page" and "a card
       lying on a table". aspect-ratio gives a definite height, so the inner
       element's `height: 100%` still resolves. */
    height: auto;
    aspect-ratio: var(--nv-ratio);
  }
}

.nv-card__inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  /* ONLY transform. box-shadow used to transition alongside it, and a
     shadow cannot be composited — every frame of the turn was a full
     repaint of a card-sized blur. */
  transition: transform var(--nv-flip-dur) var(--nv-ease);
  /* rotateY is driven by a variable so a drag can write a live angle into
     it without fighting the class-based end states. The scale that used to
     live here has moved to .nv-card — see the lift animation below. */
  transform: rotateY(var(--nv-turn, 0deg));
  border-radius: var(--nv-radius);
  box-shadow: var(--nv-shadow);
  /* Hold the composited layer instead of building it when the first flip
     starts. On this page the card IS the content, so the memory is going to
     be spent anyway; paying for it up front removes the hitch on the very
     first turn, which is the one every visitor sees. */
  will-change: transform;
  /* Vertical scrolling stays the browser's; horizontal is ours, for the
     drag-to-flip. Without this the browser claims the gesture first and the
     drag never gets a pointermove it is allowed to preventDefault. */
  touch-action: pan-y;
}

.nv-card[data-face="back"] .nv-card__inner {
  /* Negative, so in an RTL page the card opens the way the reader's eye
     already travels. */
  --nv-turn: -180deg;
}

/* While a drag is in progress the angle is written on every pointer move;
   a transition would fight it and feel like lag. */
.nv-card.is-dragging .nv-card__inner { transition: none; }

/* The lift.
   The card dips slightly as it turns and is back at full size at the moment
   the rotation lands — one motion.

   It is a KEYFRAME, not a class-toggled transition. The old version added
   scale(.94) on flip and removed it 760ms later, so the card finished
   rotating at 768ms and then spent another ~380ms visibly zooming back in
   with nothing else happening. A keyframe returns to 1 on its own, inside
   the same duration, and cannot leave a rebound behind.

   It runs on .nv-card rather than .nv-card__inner so it never touches the
   rotation, which a drag writes to directly. */
.nv-card.is-flipping { animation: nv-lift var(--nv-flip-dur) var(--nv-ease-soft); }

@keyframes nv-lift {
  0%   { transform: scale(1); }
  45%  { transform: scale(.965); }
  100% { transform: scale(1); }
}

/* Held, not animated: during a drag the card stays lifted for as long as the
   finger is down, however long that is, and eases back on release via the
   transition above. A drag release therefore does NOT run the keyframe —
   see `noLift` in nv-card.js — because restarting it from scale(1) would pop
   the card up before dipping it again. */
.nv-card.is-dragging { transform: scale(.965); transition: transform 120ms linear; }

.nv-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--nv-radius);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
  /* A repaint inside one face — the gallery cross-fade, an accordion panel
     growing — cannot invalidate anything outside it. */
  contain: paint;
}

.nv-face--back {
  transform: rotateY(180deg) translateZ(0);
  background: var(--nv-back-bg);
  color: var(--nv-back-fg);
}

/* The hidden face also gets `inert` from JS. This is the CSS half: no
   stray hover states or scroll capture through a face nobody can see. */
.nv-card[data-face="front"] .nv-face--back,
.nv-card[data-face="back"] .nv-face--front { pointer-events: none; }

/* The sheen that used to live here has been removed.

   It was a 105deg gradient band across a box inset -30% beyond the face,
   faded in and out by opacity. Two problems: it was far too wide to read as
   a glint — it looked like a grey wash passing over the card — and it forced
   an extra layer the size of the face to be painted for the whole turn.
   The rotation and the lift carry the effect on their own. */

@media (prefers-reduced-motion: reduce) {
  /* No spin, no sheen, no lift — just show the other side. */
  .nv-card__inner { transition: opacity 200ms linear; }
  .nv-card[data-face="back"] .nv-card__inner { --nv-turn: 0deg; }
  .nv-face { backface-visibility: visible; transition: opacity 200ms linear; }
  .nv-face--back { transform: none; }
  .nv-card[data-face="front"] .nv-face--back,
  .nv-card[data-face="back"] .nv-face--front { opacity: 0; }
  .nv-card.is-flipping { animation: none; }
  .nv-card.is-dragging { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   FRONT
   ══════════════════════════════════════════════════════════════════════ */

.nv-face--front {
  background: var(--nv-front-base);
  color: var(--nv-front-fg);
}

.nv-gallery { position: absolute; inset: 0; z-index: 0; }

.nv-gallery__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--nv-ease-soft);
}
.nv-gallery__slide.is-active { opacity: 1; }

.nv-gallery__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Two scrims, not one: the top darkens just enough for the white chrome
   buttons to stay legible over a bright photo, the bottom carries the
   title block. A single full-height gradient greys out the picture. */
.nv-gallery__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    var(--nv-scrim-top) 0%,
    var(--nv-scrim-mid) 26%,
    var(--nv-scrim-mid) 42%,
    var(--nv-scrim-bottom) 100%);
}

.nv-front__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--nv-pad);
  box-sizing: border-box;
  gap: .75rem;
}

/* ── chrome ─────────────────────────────────────────────────────────── */

.nv-chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
}
.nv-chrome__group { display: flex; gap: .4rem; }

.nv-iconbtn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid var(--nv-front-line);
  border-radius: 12px;
  background: var(--nv-front-fill);
  color: var(--nv-front-fg);
  font: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  position: relative;
  transition: background-color .2s var(--nv-ease-soft), transform .12s var(--nv-ease-soft);
}
.nv-iconbtn:hover { background: var(--nv-front-fill-hi); }
.nv-iconbtn:active { transform: scale(.92); }
.nv-iconbtn svg { width: 17px; height: 17px; display: block; }

/* A single quiet pulse ring, only on the memories button, only while the
   visitor has not opened it yet. */
.nv-iconbtn__ring {
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 1.5px solid var(--nv-front-fg);
  opacity: 0;
  animation: nv-ring 2.6s var(--nv-ease-soft) infinite;
  pointer-events: none;
}
@keyframes nv-ring {
  0%   { opacity: .55; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(1.28); }
  100% { opacity: 0;   transform: scale(1.28); }
}
@media (prefers-reduced-motion: reduce) { .nv-iconbtn__ring { display: none; } }

/* ── identity ───────────────────────────────────────────────────────── */

.nv-id {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: .55rem;
  min-height: 0;
}

/* Round, not a squircle. A business logo is almost always a mark drawn to
   sit in a circle — that is what every social profile and every messenger
   crops it to — so a rounded square puts corners around something already
   designed without them. 50% on the frame and on the image, with the 3px
   padding making the ring read as a ring rather than a stroke. */
.nv-id__logo {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  padding: 3px;
  background: var(--nv-front-fill);
  border: 1px solid var(--nv-front-line);
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .6);
  flex: none;
}
.nv-id__logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

.nv-id__title {
  margin: 0;
  font-size: clamp(1.5rem, 6vw, 2rem);
  font-weight: 800;
  letter-spacing: -.015em;
  line-height: 1.35;
  overflow-wrap: anywhere;
  max-width: 100%;
  /* Baseline protection for browsers without paint-order: four offset
     shadows make a hard 1px rim, the blurred one lifts it off the photo.
     A single soft shadow disappears the moment the picture behind it is
     pale, which is exactly when the white title needs help. */
  text-shadow:
     1px  1px 0 var(--nv-front-outline),
    -1px  1px 0 var(--nv-front-outline),
     1px -1px 0 var(--nv-front-outline),
    -1px -1px 0 var(--nv-front-outline),
     0 2px 14px rgba(0, 0, 0, .5);
}

@supports (paint-order: stroke) {
  /* The real thing: a stroke painted BEHIND the fill. Without paint-order a
     text-stroke is drawn on top and eats into the letterforms, which wrecks
     connected Persian script in particular. */
  .nv-id__title {
    paint-order: stroke fill;
    -webkit-text-stroke: 3.5px var(--nv-front-outline);
    text-stroke: 3.5px var(--nv-front-outline);
    text-shadow: 0 2px 14px rgba(0, 0, 0, .5);
  }
}

/* The caption: business type, a separator, and the open/closed state, all on
   one line. Three stacked pills is what made the front look busy — this is
   one control, and pressing it turns the card to the working hours. */
.nv-meta {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  max-width: 100%;
  padding: .32rem .8rem;
  border-radius: 999px;
  border: 1px solid var(--nv-front-line);
  background: var(--nv-front-fill);
  color: var(--nv-front-fg-soft);
  font: inherit;
  font-size: .8rem;
  line-height: 1.7;
  cursor: pointer;
  transition: background-color .2s var(--nv-ease-soft), transform .12s var(--nv-ease-soft);
}
.nv-meta:hover:not(:disabled) { background: var(--nv-front-fill-hi); }
.nv-meta:active:not(:disabled) { transform: scale(.96); }
/* Disabled only means "no hours to show" — it must still read normally, so
   no dimming here, just no pointer. */
.nv-meta:disabled { cursor: default; }

.nv-meta__type {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.nv-meta__sep { opacity: .5; flex: none; }

.nv-meta__dot {
  position: relative;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
  color: var(--nv-front-fg-soft);
}
.nv-meta__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: currentColor;
  animation: nv-pulse 1.9s var(--nv-ease-soft) infinite;
}
@keyframes nv-pulse {
  0%   { opacity: .75; transform: scale(1); }
  75%  { opacity: 0;   transform: scale(2.6); }
  100% { opacity: 0;   transform: scale(2.6); }
}
@media (prefers-reduced-motion: reduce) { .nv-meta__dot::after { display: none; } }

.nv-meta__status { font-weight: 700; white-space: nowrap; flex: none; }

.nv-meta.is-open   .nv-meta__dot,
.nv-meta.is-open   .nv-meta__status { color: var(--nv-open); }
.nv-meta.is-closed .nv-meta__dot,
.nv-meta.is-closed .nv-meta__status { color: var(--nv-closed); }

/* ── gallery dots ───────────────────────────────────────────────────── */

.nv-dots {
  display: flex;
  justify-content: center;
  gap: .3rem;
}
.nv-dots__dot {
  appearance: none;
  border: 0;
  padding: 0;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--nv-front-fg);
  opacity: .35;
  cursor: pointer;
  transition: opacity .25s var(--nv-ease-soft), width .25s var(--nv-ease-soft);
}
.nv-dots__dot.is-active { opacity: 1; width: 18px; }

/* ── actions ────────────────────────────────────────────────────────── */

.nv-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem;
}

.nv-pill {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .9rem;
  min-height: 40px;
  border-radius: 999px;
  border: 1px solid var(--nv-front-line);
  background: var(--nv-front-fill);
  color: var(--nv-front-fg);
  font: inherit;
  font-size: .85rem;
  font-weight: 700;
  cursor: pointer;
  transition: background-color .2s var(--nv-ease-soft), transform .12s var(--nv-ease-soft);
}
.nv-pill:hover { background: var(--nv-front-fill-hi); }
.nv-pill:active { transform: scale(.96); }

.nv-pill--donate {
  color: var(--nv-gold);
  border-color: color-mix(in srgb, var(--nv-gold) 55%, transparent);
  background: var(--nv-gold-soft);
}
/* color-mix is recent; without it the border simply falls back to the
   generic front line colour set above, which still looks correct. */

/* Glass, like every other control on this face. It stays the primary
   element by being the only full-width one and by carrying a brighter fill
   and a hairline top highlight — not by being a solid slab of accent colour
   dropped on someone's photograph. */
.nv-cta {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  width: 100%;
  box-sizing: border-box;
  min-height: 54px;
  padding: 0 1.1rem;
  border: 1px solid var(--nv-front-line);
  border-radius: 16px;
  background: var(--nv-front-fill-hi);
  color: var(--nv-front-fg);
  font: inherit;
  font-size: 1rem;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  box-shadow: 0 10px 26px -14px rgba(0, 0, 0, .7);
  transition: background-color .2s var(--nv-ease-soft), transform .14s var(--nv-ease-soft);
}
/* The highlight that makes glass look like glass rather than like a flat
   translucent rectangle. */
.nv-cta::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 50%;
  background: linear-gradient(to bottom, rgba(255, 255, 255, .16), transparent);
  pointer-events: none;
}
.nv-cta:hover { background: rgba(255, 255, 255, .38); }
.nv-cta:active { transform: scale(.98); }

/* The turn affordance. A drag anywhere on the card already flips it, so a
   second full-width button under the call to action was competing with it
   for attention. A grab handle plus a quiet label says "there is more this
   way" without claiming to be an action of equal weight. */
.nv-handle {
  appearance: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .3rem;
  width: 100%;
  padding: .35rem 0 0;
  border: 0;
  background: none;
  color: var(--nv-front-fg-soft);
  font: inherit;
  cursor: pointer;
  transition: color .2s var(--nv-ease-soft);
}
.nv-handle:hover { color: var(--nv-front-fg); }
.nv-handle__bar {
  width: 46px;
  height: 4px;
  border-radius: 999px;
  background: currentColor;
  opacity: .55;
  transition: width .25s var(--nv-ease), opacity .2s var(--nv-ease-soft);
}
.nv-handle:hover .nv-handle__bar { width: 62px; opacity: .9; }
.nv-handle__text {
  font-size: .74rem;
  font-weight: 600;
  text-shadow: 0 1px 3px var(--nv-front-outline);
}

/* ═══════════════════════════════════════════════════════════════════════
   BACK
   ══════════════════════════════════════════════════════════════════════ */

.nv-back__head {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .85rem var(--nv-pad);
  background: var(--nv-back-bg-2);
  border-bottom: 1px solid var(--nv-line);
  flex: none;
}
.nv-back__logo {
  width: 38px;
  height: 38px;
  border-radius: 12px;
  object-fit: cover;
  flex: none;
  border: 1px solid var(--nv-line);
}
.nv-back__titles { flex: 1; min-width: 0; }
.nv-back__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nv-back__sub {
  font-size: .72rem;
  color: var(--nv-back-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nv-back__close {
  appearance: none;
  width: 36px;
  height: 36px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--nv-line);
  border-radius: 11px;
  background: var(--nv-surface);
  color: var(--nv-back-fg);
  font-size: 14px;
  cursor: pointer;
  transition: background-color .2s var(--nv-ease-soft), transform .12s var(--nv-ease-soft);
}
.nv-back__close:hover { background: var(--nv-surface-hi); }
.nv-back__close:active { transform: scale(.92); }
.nv-back__close svg { width: 15px; height: 15px; }

/* The scroll region. Only this scrolls — the header above and the credit
   below stay put, which is the requirement that every other section
   heading remains reachable while one is open. */
.nv-back__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: .75rem var(--nv-pad) 1rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  scrollbar-width: thin;
  scrollbar-color: var(--nv-line) transparent;
}
.nv-back__list::-webkit-scrollbar { width: 6px; }
.nv-back__list::-webkit-scrollbar-thumb {
  background: var(--nv-line);
  border-radius: 999px;
}
.nv-back__list::-webkit-scrollbar-track { background: transparent; }

/* ── section (accordion row) ────────────────────────────────────────── */

.nv-sec {
  /* The list is a flex column, so without this every section SHRINKS to make
     the content fit instead of overflowing — the list then reports nothing to
     scroll while the open panel is quietly squashed and the last heading is
     clipped by the face. */
  flex: 0 0 auto;
  border: 1px solid var(--nv-line);
  border-radius: 16px;
  background: var(--nv-surface);
  overflow: hidden;
  transition: border-color .25s var(--nv-ease-soft), box-shadow .25s var(--nv-ease-soft);
}
.nv-sec.is-open {
  border-color: color-mix(in srgb, var(--nv-accent) 45%, var(--nv-line));
  box-shadow: 0 6px 22px -14px rgba(0, 0, 0, .55);
}

.nv-sec__head {
  appearance: none;
  display: flex;
  align-items: center;
  gap: .7rem;
  width: 100%;
  box-sizing: border-box;
  padding: .8rem .9rem;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
  min-height: 52px;
  transition: background-color .2s var(--nv-ease-soft);
}
.nv-sec__head:hover { background: var(--nv-surface-hi); }

.nv-sec__icon {
  width: 34px;
  height: 34px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  background: var(--nv-accent-soft);
  color: var(--nv-accent);
  font-size: 14px;
}
.nv-sec.is-open .nv-sec__icon { background: var(--nv-accent); color: var(--nv-accent-fg); }

.nv-sec__label { flex: 1; min-width: 0; }
/* These are <span>s so the whole heading can stay one <button>; without an
   explicit block they run together on a single line. */
.nv-sec__title {
  display: block;
  font-size: .92rem; font-weight: 700; line-height: 1.6;
}
.nv-sec__hint {
  display: block;
  font-size: .72rem;
  color: var(--nv-back-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nv-sec__chev {
  flex: none;
  color: var(--nv-back-muted);
  font-size: 12px;
  transition: transform .3s var(--nv-ease), color .2s var(--nv-ease-soft);
}
.nv-sec.is-open .nv-sec__chev { transform: rotate(180deg); color: var(--nv-accent); }

/* The panel animates on max-height, set in pixels by the script from the
   content's own scrollHeight. `height: auto` cannot be transitioned, and a
   guessed max-height either clips long content or makes short content
   sluggish because the transition has to travel the whole guess. */
.nv-sec__panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height .38s var(--nv-ease);
}
.nv-sec.is-open > .nv-sec__panel { max-height: var(--nv-panel-h, 60vh); }

/* Once open, a very long panel scrolls inside itself rather than pushing
   every other section heading out of reach. */
.nv-sec__panelinner {
  padding: .2rem .9rem .9rem;
  max-height: 46vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--nv-line) transparent;
}
.nv-sec__panelinner::-webkit-scrollbar { width: 5px; }
.nv-sec__panelinner::-webkit-scrollbar-thumb {
  background: var(--nv-line);
  border-radius: 999px;
}

@media (prefers-reduced-motion: reduce) {
  .nv-sec__panel { transition: none; }
  .nv-sec__chev { transition: none; }
}

/* ── content primitives used inside panels ──────────────────────────── */

.nv-row {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .6rem .7rem;
  border-radius: 12px;
  background: var(--nv-surface-hi);
  color: inherit;
  text-decoration: none;
  transition: background-color .2s var(--nv-ease-soft);
}
.nv-row + .nv-row { margin-top: .4rem; }

/* The branch you are already on, at the top of the شعبه chooser. Tinted so
   the list reads as "here, and these others" rather than as a flat set of
   equally likely links. */
.nv-row--primary {
  background: var(--nv-accent-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-accent) 32%, transparent);
}
.nv-row--primary .nv-row__ico { color: var(--nv-accent); }
.nv-row:hover { background: color-mix(in srgb, var(--nv-accent) 8%, var(--nv-surface-hi)); }

.nv-row__ico {
  width: 30px;
  height: 30px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: var(--nv-surface);
  color: var(--nv-accent);
  font-size: 12px;
  border: 1px solid var(--nv-line);
  overflow: hidden;
}
.nv-row__ico img { width: 18px; height: 18px; object-fit: contain; }

.nv-row__body { flex: 1; min-width: 0; }
.nv-row__label {
  display: block;
  font-size: .7rem;
  color: var(--nv-back-muted);
  line-height: 1.5;
}
.nv-row__value {
  display: block;
  font-size: .86rem;
  font-weight: 600;
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.nv-row__value--ltr {
  direction: ltr;
  text-align: start;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

.nv-row__act {
  appearance: none;
  flex: none;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 10px;
  background: var(--nv-accent);
  color: var(--nv-accent-fg);
  font-size: 12px;
  cursor: pointer;
  transition: transform .12s var(--nv-ease-soft), filter .2s var(--nv-ease-soft);
}
.nv-row__act:hover { filter: brightness(1.08); }
.nv-row__act:active { transform: scale(.9); }
.nv-row__act--ghost {
  background: var(--nv-surface);
  color: var(--nv-back-muted);
  border: 1px solid var(--nv-line);
}

.nv-text {
  font-size: .86rem;
  line-height: 2;
  color: var(--nv-back-fg);
  white-space: pre-line;
  overflow-wrap: anywhere;
  margin: 0;
}

.nv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: .45rem;
}
.nv-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .3rem;
  padding: .6rem .3rem;
  border-radius: 12px;
  background: var(--nv-surface-hi);
  color: inherit;
  text-decoration: none;
  font-size: .68rem;
  font-weight: 600;
  text-align: center;
  transition: background-color .2s var(--nv-ease-soft), transform .12s var(--nv-ease-soft);
}
.nv-tile:hover { background: color-mix(in srgb, var(--nv-accent) 10%, var(--nv-surface-hi)); }
.nv-tile:active { transform: scale(.95); }
.nv-tile__ico { font-size: 17px; color: var(--nv-accent); line-height: 1; }
.nv-tile__ico img { width: 20px; height: 20px; object-fit: contain; }
.nv-tile span {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* hours */
.nv-hours { display: flex; flex-direction: column; gap: .3rem; }
.nv-hours__day {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  padding: .45rem .65rem;
  border-radius: 10px;
  background: var(--nv-surface-hi);
  font-size: .8rem;
}
.nv-hours__day.is-today {
  background: var(--nv-accent-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-accent) 35%, transparent);
}
.nv-hours__name { font-weight: 700; }
.nv-hours__shifts { display: flex; flex-wrap: wrap; gap: .3rem; justify-content: flex-end; }
.nv-hours__shift {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  direction: ltr;
  padding: .1rem .45rem;
  border-radius: 7px;
  background: var(--nv-surface);
  border: 1px solid var(--nv-line);
  font-variant-numeric: tabular-nums;
  font-size: .78rem;
}
.nv-hours__shift i { font-size: 10px; }
.nv-hours__shift .nv-sun  { color: var(--nv-gold); }
.nv-hours__shift .nv-moon { color: var(--nv-accent); }
.nv-hours__closed { color: var(--nv-closed); font-weight: 700; font-size: .76rem; }

/* ── credit ─────────────────────────────────────────────────────────── */

.nv-credit {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: .7rem;
  padding-bottom: max(.7rem, env(safe-area-inset-bottom));
  background: var(--nv-back-bg-2);
  border-top: 1px solid var(--nv-line);
  color: var(--nv-back-muted);
  font-size: .74rem;
  text-decoration: none;
  transition: color .2s var(--nv-ease-soft);
}
.nv-credit:hover { color: var(--nv-accent); }
.nv-credit b { color: var(--nv-back-fg); font-weight: 800; }
.nv-credit:hover b { color: var(--nv-accent); }

/* ── shared ─────────────────────────────────────────────────────────── */

.nv-empty {
  text-align: center;
  color: var(--nv-back-muted);
  font-size: .82rem;
  padding: 2rem 1rem;
}

:where(.nv-card) :focus-visible {
  outline: 2px solid var(--nv-accent);
  outline-offset: 2px;
  border-radius: 8px;
}
/* The front face sits on a photo, where the accent blue can vanish. */
.nv-face--front :focus-visible { outline-color: var(--nv-front-fg); }

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

/* ── very short viewports ───────────────────────────────────────────── */

@media (max-height: 640px) {
  .nv-card { --nv-pad: 1rem; }
  .nv-id { gap: .4rem; }
  .nv-id__logo { width: 62px; height: 62px; }
  .nv-id__title { font-size: clamp(1.25rem, 5.5vw, 1.6rem); }
  .nv-cta { min-height: 48px; }
  .nv-handle__text { font-size: .7rem; }
}
@media (max-height: 560px) {
  /* Below this the type chip and the dots are the first things a visitor
     stops needing; the title, status and buttons are not. */
  .nv-meta__type, .nv-meta__sep, .nv-dots { display: none; }
  .nv-id__logo { width: 52px; height: 52px; }
}


/* The call to action inside a sheet sits on the BACK surface, not on a
   photograph, so the glass treatment that works on the front face would be
   nearly invisible here. Same shape, accent fill. */
.nv-sheet .nv-cta {
  border-color: transparent;
  background: var(--nv-accent, #2563eb);
  color: var(--nv-accent-fg, #fff);
  box-shadow: 0 10px 24px -14px rgba(0, 0, 0, .6);
}
.nv-sheet .nv-cta:hover { background: var(--nv-accent, #2563eb); filter: brightness(1.07); }
.nv-sheet .nv-cta::before { background: linear-gradient(to bottom, rgba(255,255,255,.14), transparent); }

/* The story grid's `md:grid-cols-3` is a VIEWPORT media query, but inside the
   sheet the available width is the card's ~416px no matter how wide the
   window is — three columns there gives 110px tiles. Two, always. */
.nv-sheet #story-grid {
  /* display:grid too, not just the columns: the element gets its `display`
     from a Tailwind utility, and a rule that assumes the utility survived
     the build is a rule that fails silently the day it does not. */
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .6rem;
  padding: .75rem;
}

/* ══════════════════════════════════════════════════════════════════════
   NORIVA'S RECOMMENDATION — the last row of the back
   ══════════════════════════════════════════════════════════════════════
   Filled by nv-reco.js (see spotlight/). It is an .nv-row with the shape of
   a section heading beside it: same border, same radius, same height, same
   tokens — so a business's card customisation recolours it with everything
   else, and it reads as one more line of the card rather than an insert.
   Nothing here animates, and the label says what it is. */

.nv-reco { flex: 0 0 auto; }
.nv-reco[hidden] { display: none; }

.nv-back__list .nv-reco__row {
  gap: .5rem;
  min-height: 52px;
  box-sizing: border-box;
  padding: .45rem .55rem .45rem .5rem;
  border: 1px solid var(--nv-line);
  border-radius: 16px;
  background: var(--nv-surface);
}
.nv-back__list .nv-reco__row:hover { background: var(--nv-surface-hi); }

.nv-reco__main {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: .65rem;
  color: inherit;
  text-decoration: none;
}

/* The small image fills its tile, unlike the row icons it sits beside,
   which are glyphs centred in theirs. */
.nv-reco__ico.nv-row__ico { width: 34px; height: 34px; border-radius: 11px; }
.nv-reco__ico img { width: 100%; height: 100%; object-fit: cover; display: block; }
.nv-reco__ico.is-letter { font-size: .85rem; font-weight: 800; }

.nv-reco__label.nv-row__label { font-size: .66rem; }
.nv-reco__title.nv-row__value {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow-wrap: normal;
}
.nv-reco__text {
  display: block;
  font-size: .7rem;
  line-height: 1.5;
  color: var(--nv-back-muted);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.nv-reco__act { text-decoration: none; }
.nv-reco__act svg { width: 14px; height: 14px; }
