/* ============================================================================
   CROMA MNL — public website
   Same warm Japandi palette as the POS and community app so all three read as one
   brand, retuned for a desktop-first marketing site.

   Design constraint worth knowing: there are no café photographs yet, so the
   visual interest has to come from type scale, colour, texture and spacing
   rather than imagery. Hence the layered gradients, the grain overlay and the
   oversized wordmark — they carry the page until real photos replace them.
   ========================================================================== */
:root{
  --bg:#e9e3d6; --surface:#fbf8f2; --surface2:#f1ebdd; --line:#ddd3c1;
  --text:#3a2b20; --muted:#8a7c66; --brand:#5b3f2c; --brand-2:#6f4e37;
  --accent:#b5895a; --accent-soft:#e8d9c3; --green:#6f8259; --red:#b0574f;
  --radius:18px; --radius-sm:12px;
  --shadow:0 4px 18px rgba(58,43,32,.07);
  --shadow-lg:0 18px 46px rgba(58,43,32,.14);
  --wrap:1140px;
  --ease:cubic-bezier(.22,.61,.36,1);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  background:var(--bg);color:var(--text);
  font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;line-height:1.62;
}
img{max-width:100%;display:block}
a{color:var(--brand-2);text-decoration:none}
a:hover{text-decoration:underline}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 22px}
.muted{color:var(--muted)}
.small{font-size:13px}
.center{text-align:center}
h1,h2,h3,h4{line-height:1.15;letter-spacing:-.015em}

/* Fade-in-on-scroll. NOTE the `.js` guard: the hidden start state applies ONLY once the script
   has run and added that class. Without it the content is plain visible — a broken script or a
   browser without IntersectionObserver must never leave the page blank. Also disabled outright
   for anyone who asks for reduced motion. */
.js .rise{opacity:0;transform:translateY(18px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.js .rise.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .rise{opacity:1;transform:none;transition:none}
}

/* ---- header ---- */
.site-head{position:sticky;top:0;z-index:30;background:rgba(233,227,214,.86);
  backdrop-filter:saturate(150%) blur(12px);border-bottom:1px solid rgba(221,211,193,.8);
  transition:box-shadow .25s var(--ease)}
.site-head.stuck{box-shadow:0 4px 20px rgba(58,43,32,.09)}
.site-head .wrap{display:flex;align-items:center;gap:20px;height:80px}
/* The logo was previously 30px and vanished. Fluid, and much larger. */
.site-head picture{display:flex;align-items:center}
.site-head .logo{height:clamp(44px,4.6vw,56px);width:auto}
.site-nav{margin-left:auto;display:flex;gap:26px;align-items:center}
.site-nav a{color:var(--text);font-weight:600;font-size:15.5px;position:relative;padding:4px 0}
.site-nav a:not(.btn):hover{text-decoration:none}
.site-nav a:not(.btn)::after{content:'';position:absolute;left:0;right:100%;bottom:0;height:2px;
  background:var(--accent);transition:right .3s var(--ease)}
.site-nav a:not(.btn):hover::after,.site-nav a.active::after{right:0}
.navtoggle{display:none;margin-left:auto;background:var(--surface);border:1px solid var(--line);
  border-radius:12px;padding:9px 13px;font-size:18px;cursor:pointer;color:var(--text)}

/* ---- buttons ---- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:14px 26px;border-radius:13px;font-weight:700;font-size:15.5px;
  border:1px solid var(--line);background:var(--surface);color:var(--text);
  cursor:pointer;transition:transform .18s var(--ease),box-shadow .18s var(--ease),background .18s}
.btn:hover{text-decoration:none;transform:translateY(-2px);box-shadow:var(--shadow-lg)}
.btn.primary{background:var(--brand);border-color:var(--brand);color:#faf6ee}
.btn.primary:hover{background:var(--brand-2)}
.btn.accent{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.lg{padding:17px 34px;font-size:17px}

/* ---- hero ---- */
.hero{position:relative;overflow:hidden;padding:88px 0 78px;text-align:center;
  background:
    radial-gradient(900px 420px at 50% -12%,rgba(181,137,90,.28),transparent 70%),
    radial-gradient(600px 340px at 12% 108%,rgba(111,78,55,.14),transparent 70%),
    linear-gradient(180deg,#efe9dd,#e9e3d6);
}
/* Faint grain so the large flat areas don't read as an unfinished template. */
.hero::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;
  background-image:radial-gradient(rgba(91,63,44,.12) 1px,transparent 1px);
  background-size:26px 26px}
.hero .inner{position:relative;z-index:1}
.hero picture{display:block;width:-moz-fit-content;width:fit-content;margin:0 auto}
.hero .mark{height:clamp(96px,12vw,150px);width:auto;margin:0 0 28px;
  filter:drop-shadow(0 6px 18px rgba(58,43,32,.14))}
.hero h1{font-size:clamp(31px,5.4vw,54px);color:var(--brand);max-width:16ch;margin:0 auto}
.hero p.lead{font-size:clamp(16.5px,1.9vw,20px);color:#6b5b47;max-width:60ch;margin:22px auto 0}
.hero .cta{display:flex;gap:13px;justify-content:center;flex-wrap:wrap;margin-top:34px}
.hero .quickfacts{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:34px}
.pill{background:rgba(251,248,242,.86);border:1px solid var(--line);border-radius:999px;
  padding:9px 17px;font-size:14px;font-weight:600;display:inline-flex;align-items:center;gap:8px}

/* ---- sections ---- */
section{padding:76px 0}
.alt{background:var(--surface2)}
.dark{background:linear-gradient(160deg,#5b3f2c,#4a3223);color:#f0e6d8}
.sec-head{text-align:center;max-width:66ch;margin:0 auto 44px}
.sec-head .eyebrow{font-size:12.5px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent);margin-bottom:12px}
.sec-head h1,.sec-head h2{font-size:clamp(25px,3.6vw,38px);color:var(--brand)}
.sec-head p{color:var(--muted);margin-top:12px;font-size:17px}

/* ---- cards ---- */
.grid{display:grid;gap:20px}
.g2{grid-template-columns:repeat(auto-fit,minmax(330px,1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(285px,1fr))}
.g4{grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:26px;box-shadow:var(--shadow);transition:transform .22s var(--ease),box-shadow .22s var(--ease)}
.card.hoverable:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg)}
.card .ic{font-size:30px;line-height:1;margin-bottom:14px}
.card h3{font-size:19.5px;color:var(--brand);margin-bottom:9px}
.card p{color:var(--muted);font-size:15px}
.dark .card{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.14);box-shadow:none}
.dark .card p{color:#cdbca6}

/* ---- dark-panel overrides ----------------------------------------------------------------
   These MUST come after .sec-head h2 / .card h3 / .card p and carry higher specificity, or those
   later brand-brown rules win at equal specificity and render brown text on a brown panel. */
.dark .sec-head h1,.dark .sec-head h2,.dark .card h3,.dark h1,.dark h2,.dark h3{color:#fff}
.dark .sec-head p,.dark .card p,.dark .muted{color:#d8c9b3}
.dark .sec-head .eyebrow{color:var(--accent-soft)}

/* amenity tiles — the work-friendly pitch */
.amen{display:flex;gap:14px;align-items:flex-start;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);padding:20px}
.amen .ic{font-size:25px;flex:none;line-height:1.2}
.amen strong{display:block;font-size:16px;color:var(--brand)}
.amen span{font-size:14px;color:var(--muted)}

/* numbered steps */
.step{position:relative;padding-left:56px}
.step .n{position:absolute;left:0;top:-2px;width:40px;height:40px;border-radius:50%;
  background:var(--accent-soft);color:var(--brand);font-weight:800;font-size:17px;
  display:flex;align-items:center;justify-content:center}

/* ---- menu ---- */
.menu-cat{margin-top:44px}
.menu-cat h3{font-size:24px;color:var(--brand);padding-bottom:12px;
  border-bottom:2px solid var(--accent-soft);display:flex;align-items:baseline;gap:12px}
.menu-cat h3 .count{font-size:13px;font-weight:600;color:var(--muted);letter-spacing:.04em}
.menu-items{display:grid;gap:14px;margin-top:20px;grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.mi{background:var(--surface);border:1px solid var(--line);border-radius:14px;overflow:hidden;
  transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
.mi:hover{transform:translateY(-3px);box-shadow:var(--shadow-lg)}
/* Item photos appear automatically as soon as they're uploaded in the POS; until then the card
   is text-only and the grid still looks intentional rather than broken. */
.mi .ph{aspect-ratio:4/3;background:var(--surface2) center/cover no-repeat;
  border-bottom:1px solid var(--line)}
.mi .tx{padding:14px 16px}
/* The favourite mark, bottom-right of the card, on its own row with the Hot or
   iced tag. IN FLOW, not absolutely positioned — pinned to the corner it would
   sooner or later land on the last line of a long description, and only on the
   products whose text happens to run that far. margin-left:auto is what holds
   it right whether or not the tag is there to sit beside it.
   No halo down here: it is on the cream card, not on a photograph, where the
   wordmark brown measures 11.7:1 and needs no help. */
.mi .foot{display:flex;align-items:center;gap:8px;margin-top:8px}
.mi .foot .tag{margin-top:0}
.fav-foot{margin-left:auto;margin-right:0;flex:none}
.mi .n{font-weight:700;font-size:15.5px}
.mi .d{font-size:13px;color:var(--muted);margin-top:3px}
.mi .tag{display:inline-block;margin-top:8px;font-size:11.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--accent);background:var(--accent-soft);
  border-radius:6px;padding:3px 8px}
.menu-note{margin-top:38px;padding:22px;background:var(--surface);border:1px dashed var(--line);
  border-radius:var(--radius);text-align:center;color:var(--muted);font-size:15px}

/* ---- events ---- */
.ev{display:flex;gap:18px;align-items:flex-start;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);padding:22px;box-shadow:var(--shadow);
  transition:transform .22s var(--ease),box-shadow .22s var(--ease)}
.ev:hover{transform:translateY(-3px);box-shadow:var(--shadow-lg)}
.ev .when{flex:none;width:76px;text-align:center;background:var(--accent-soft);
  border-radius:14px;padding:12px 6px}
.ev .when .d{font-size:26px;font-weight:800;color:var(--brand);line-height:1}
.ev .when .m{font-size:11.5px;font-weight:800;color:var(--brand-2);text-transform:uppercase;letter-spacing:.08em}
.ev h3{font-size:18.5px;color:var(--brand)}
.ev .meta{font-size:13px;color:var(--muted);margin-top:5px}
.ev p{font-size:14.5px;margin-top:10px;color:#5f5140}

/* ---- forms ---- */
label{display:block;font-size:13px;font-weight:700;color:var(--muted);margin:16px 0 7px}
input,textarea,select{width:100%;padding:13px 15px;border:1px solid var(--line);
  border-radius:12px;background:var(--surface);color:var(--text);font:inherit;font-size:15.5px}
input:focus,textarea:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
textarea{min-height:130px;resize:vertical}
.formmsg{min-height:22px;font-size:14px;margin-top:11px}

/* ---- footer ---- */
.site-foot{background:linear-gradient(160deg,#4a3223,#3a2618);color:#e0d3c0;padding:58px 0 28px;margin-top:0}
.site-foot a{color:#f2e9dc}
.site-foot .cols{display:grid;gap:32px;grid-template-columns:1.4fr 1fr 1fr}
.site-foot h4{font-size:12.5px;text-transform:uppercase;letter-spacing:.14em;margin-bottom:14px;color:#fff}
.site-foot picture{display:block}
.site-foot .flogo{height:44px;width:auto;margin-bottom:14px;
  filter:brightness(0) invert(1) opacity(.92)}
.site-foot p,.site-foot li{font-size:14.5px;color:#cdbca6}
.site-foot .socials{display:flex;gap:11px;margin-top:16px}
.site-foot .socials a{width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.11);
  display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;
  transition:background .2s}
.site-foot .socials a:hover{background:rgba(255,255,255,.22);text-decoration:none}
/* The marks are inline SVG using currentColor, so they inherit the footer's
   text colour and need no second palette. line-height:0 stops the anchor
   reserving a text line under a graphic that has no baseline. */
.site-foot .socials a{line-height:0;color:inherit}
.site-foot .socials svg{display:block}
.site-foot .legal{border-top:1px solid rgba(255,255,255,.15);margin-top:36px;padding-top:20px;
  font-size:13px;display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;color:#b3a28c}

/* loading placeholder for the live-fetched sections */
.skel{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  height:104px;animation:pulse 1.5s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.5}50%{opacity:.85}}

@media(max-width:820px){
  .site-foot .cols{grid-template-columns:1fr}
}
@media(max-width:760px){
  .site-head .wrap{height:70px}
  .site-nav{display:none;position:absolute;top:70px;left:0;right:0;background:var(--surface);
    flex-direction:column;gap:0;border-bottom:1px solid var(--line);box-shadow:var(--shadow-lg);padding:6px 0}
  .site-nav.open{display:flex}
  .site-nav a{padding:15px 22px;width:100%}
  .site-nav a:not(.btn)::after{display:none}
  .site-nav .btn{margin:10px 22px}
  .navtoggle{display:block}
  .ev{flex-direction:column;gap:14px}
  .ev .when{width:auto;display:inline-flex;gap:9px;align-items:baseline;padding:8px 14px}
  section{padding:52px 0}
  .hero{padding:56px 0 54px}
}

/* ---- photo gallery -------------------------------------------------------------------------
   Rendered by site.js only for files that actually load, so dropping photo-1.jpg … photo-6.jpg
   into assets/ makes them appear with no markup change, and missing ones never leave a gap. */
#galleryWrap{display:none}
#galleryWrap.has{display:block}
.gal{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.gal figure{margin:0;border-radius:var(--radius);overflow:hidden;border:1px solid var(--line);
  box-shadow:var(--shadow);background:var(--surface2)}
.gal img{width:100%;height:100%;aspect-ratio:4/3;object-fit:cover;
  transition:transform .5s var(--ease)}
.gal figure:hover img{transform:scale(1.04)}
.gal figure.wide{grid-column:span 2}
@media(max-width:700px){ .gal figure.wide{grid-column:auto} }

/* Hero photo, when assets/hero.jpg exists. The overlay keeps the headline readable over any
   image — without it, a bright photo would wash the type out completely. */
.hero.has-photo{background-image:linear-gradient(rgba(58,43,32,.62),rgba(58,43,32,.72)),var(--heroimg);
  background-size:cover;background-position:center}
.hero.has-photo::after{display:none}
.hero.has-photo h1{color:#fff;text-shadow:0 2px 18px rgba(0,0,0,.35)}
.hero.has-photo p.lead{color:#f0e6d8}
.hero.has-photo .mark{filter:brightness(0) invert(1) drop-shadow(0 4px 16px rgba(0,0,0,.4))}
.hero.has-photo .pill{background:rgba(251,248,242,.92)}

/* ==========================================================================
   DESIGN REFRESH
   ==========================================================================
   The palette was already right — warm, Japandi, unmistakably a café. What made
   the page read as unfinished was that every word on it was set in the system UI
   font: the same face as a settings dialog. A brand cannot sound like anything
   in Segoe UI.

   So: one display face, self-hosted, headings only.

   Self-hosted because the CSP is font-src 'self' data: — Google's CDN is not on
   that list and a <link> to it would be blocked outright, silently falling back
   to the system font on the live site while looking perfect locally. Serving it
   ourselves is also faster and leaves no third party in the page.

   Headings only because body text in a good system stack is genuinely fine, and
   one 67 kB file is a fair price for the whole brand voice. Two would not be.
   ========================================================================== */

@font-face{
  font-family:'Fraunces';
  src:url('../assets/fonts/fraunces-latin.woff2') format('woff2-variations');
  font-weight:400 700;                 /* variable: one file, every weight */
  font-display:swap;                   /* text is readable before the font lands */
  font-style:normal;
}

:root{
  --display:'Fraunces', Georgia, 'Times New Roman', serif;
  /* A fluid scale, so the page is composed at every width instead of at two
     breakpoints with a jump between them. */
  --step-hero:clamp(2.4rem, 1.2rem + 4.6vw, 4.6rem);
  --step-h2:clamp(1.75rem, 1.1rem + 2.2vw, 2.9rem);
  --step-h3:clamp(1.05rem, .95rem + .45vw, 1.28rem);
  --step-lead:clamp(1.02rem, .95rem + .5vw, 1.28rem);
}

h1,h2,h3,.hero h1,.sec-head h1,.sec-head h2{
  font-family:var(--display);
  font-weight:600;
  letter-spacing:-.015em;              /* a serif at display size needs tightening */
  line-height:1.12;
  text-wrap:balance;                   /* no orphaned last word in a headline */
}
h3{line-height:1.25}

.hero h1{
  font-size:var(--step-hero);
  font-weight:600;
  font-variation-settings:'opsz' 100;  /* the optical size axis: cut for display */
  letter-spacing:-.022em;
}
.sec-head h1,.sec-head h2{font-size:var(--step-h2)}
.card h3,.amen strong{font-size:var(--step-h3)}
.hero p.lead{font-size:var(--step-lead);line-height:1.62;max-width:44ch}
.sec-head p{max-width:62ch;margin-left:auto;margin-right:auto}

/* The eyebrow was doing nothing. Small caps and letterspacing make it read as a
   label rather than as a stray line of text above the headline. */
.eyebrow{
  font-family:var(--display);
  font-weight:600;font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  opacity:.9;
}

/* --- HEADER: floats over the hero, frosts once you scroll past it ---------- */
.site-head{
  backdrop-filter:saturate(1.4) blur(10px);
  -webkit-backdrop-filter:saturate(1.4) blur(10px);
  transition:background-color .28s ease, box-shadow .28s ease, padding .28s ease;
}
.site-head.stuck{box-shadow:0 1px 0 rgba(58,43,32,.09), 0 10px 30px -18px rgba(58,43,32,.45)}
.site-nav a:not(.btn){font-weight:600}

/* --- BUTTONS: the primary action should look pressable ------------------- */
.btn{
  transition:transform .16s cubic-bezier(.2,.8,.3,1), box-shadow .22s ease,
             background-color .22s ease, color .22s ease, border-color .22s ease;
  will-change:transform;
}
.btn:hover{transform:translateY(-1.5px)}
.btn:active{transform:translateY(0)}
.btn.primary{box-shadow:0 10px 24px -12px rgba(91,63,44,.75)}
.btn.primary:hover{box-shadow:0 16px 30px -14px rgba(91,63,44,.8)}
.btn.lg{border-radius:999px}          /* pill CTAs read as friendlier than boxes */
.btn:focus-visible{outline:2.5px solid var(--accent);outline-offset:3px}

/* --- HERO ---------------------------------------------------------------- */
.hero{position:relative;isolation:isolate}
/* A soft vignette so the headline sits on the darkest part of the photograph
   rather than fighting whatever the image happens to be doing behind it. */
.hero::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(115% 85% at 50% 0%, rgba(0,0,0,0) 42%, rgba(35,25,18,.42) 100%);
}
.hero .mark{filter:brightness(0) invert(1);opacity:1;
  image-rendering:auto;}   /* full opacity: .94 only made the edges muddier */
.hero .quickfacts{gap:9px}

/* --- PILLS & CARDS ------------------------------------------------------- */
.pill{
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  border-radius:999px;font-weight:600;letter-spacing:.005em;
}
.card{
  border-radius:var(--radius);
  transition:transform .22s cubic-bezier(.2,.8,.3,1), box-shadow .28s ease;
}
.card.hoverable:hover{transform:translateY(-4px);box-shadow:0 22px 44px -26px rgba(58,43,32,.6)}
.amen{transition:transform .2s ease}
.amen:hover{transform:translateX(2px)}

/* --- RHYTHM: give the page room to breathe ------------------------------- */
section{padding-block:clamp(58px, 4vw + 42px, 104px)}
.sec-head{margin-bottom:clamp(28px, 2vw + 18px, 46px)}

/* --- OPEN NOW: a live, factual signal, filled in by site.js -------------- */
/* THE OPENING BAR — the one thing on the site that is allowed to shout.
 *
 * The first version was a brown gradient, which on a brown-and-cream site is
 * camouflage: it read as part of the furniture and nobody's eye stopped on it.
 * A launch announcement has one job, so this one carries the café's own photo
 * under an espresso scrim, a warm glow that drifts, and a shine that sweeps
 * across every few seconds. The gold is deliberately NOT in the everyday
 * palette — that is what makes it read as an event rather than as chrome.
 *
 * The scrim is part of the background shorthand rather than a moving layer, so
 * the photo can never show through underneath the text while the glow drifts.
 * Contrast is carried by the scrim, not by the animation: with motion off, or
 * before the photo loads, the bar is still cream-on-espresso and perfectly
 * legible. Everything moving is decoration on top of something that already
 * works. */
.openbar{
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;align-items:center;justify-content:center;gap:12px;
  padding:13px 18px;min-height:54px;z-index:30;
  color:#fbf8f2;text-align:center;font-size:14.5px;font-weight:600;letter-spacing:.2px;line-height:1.35;
  background:
    linear-gradient(90deg,rgba(24,16,11,.94),rgba(24,16,11,.68) 50%,rgba(24,16,11,.94)),
    url('../assets/hero.jpg') center 62% / cover no-repeat,
    #24180f;
  box-shadow:inset 0 -1px 0 rgba(251,248,242,.14);
}
/* The drifting glow. Two soft pools that slide past each other, so the light
   never sits still long enough to become a texture. */
.openbar::before{
  content:'';position:absolute;inset:-60% -20%;z-index:-1;pointer-events:none;
  background:
    radial-gradient(38% 120% at 28% 50%,rgba(245,198,116,.50),transparent 62%),
    radial-gradient(34% 120% at 72% 50%,rgba(181,137,90,.45),transparent 62%);
  animation:openGlow 11s ease-in-out infinite alternate;
}
/* The shine. A single pass, then a long pause — a sweep every two seconds is
   a nightclub, one every seven reads as a sheen. */
.openbar::after{
  content:'';position:absolute;top:-60%;bottom:-60%;width:22%;z-index:-1;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.30),transparent);
  animation:openShine 7s cubic-bezier(.5,0,.5,1) infinite;
}
@keyframes openGlow{ from{transform:translateX(-9%)} to{transform:translateX(9%)} }
@keyframes openShine{ 0%{transform:translateX(-160%) skewX(-16deg)} 55%,100%{transform:translateX(560%) skewX(-16deg)} }

.openbar .ob-dot{
  width:9px;height:9px;border-radius:50%;flex:none;background:#f5c674;
  box-shadow:0 0 0 4px rgba(245,198,116,.22),0 0 12px rgba(245,198,116,.9);
  animation:openPulse 2.2s ease-in-out infinite;
}
.openbar.open .ob-dot{background:#8ed08a;box-shadow:0 0 0 4px rgba(142,208,138,.22),0 0 12px rgba(142,208,138,.9)}
@keyframes openPulse{ 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.55;transform:scale(.82)} }

/* The date itself, which is the whole message. */
.openbar b{
  font-weight:800;letter-spacing:.3px;
  background:linear-gradient(90deg,#ffd489,#f5c674 45%,#ffe3b0);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  /* A gradient-clipped text has no colour of its own if the clip is not
     supported, so a fallback colour is painted first by the rule above it. */
}
.openbar.open b{background:linear-gradient(90deg,#b7e8b0,#8ed08a 45%,#d6f5cf);-webkit-background-clip:text;background-clip:text}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .openbar b{color:#ffd489;background:none}
  .openbar.open b{color:#b7e8b0;background:none}
}

@media (max-width:560px){
  .openbar{font-size:13px;padding:11px 14px;min-height:48px;gap:9px}
  .openbar::after{width:34%}
}
@media (prefers-reduced-motion:reduce){
  .openbar::before,.openbar::after,.openbar .ob-dot{animation:none}
  .openbar::after{opacity:0}
}

.openbadge{
  display:none;align-items:center;gap:8px;margin:20px auto 0;
  padding:8px 16px;border-radius:999px;font-size:13.5px;font-weight:600;
  background:rgba(251,248,242,.14);border:1px solid rgba(251,248,242,.3);
  color:#fbf8f2;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  width:max-content;
}
.openbadge.show{display:inline-flex}
.openbadge .dot{width:8px;height:8px;border-radius:50%;background:#8ec07c;
  box-shadow:0 0 0 4px rgba(142,192,124,.22)}
.openbadge.shut .dot{background:#d98b7f;box-shadow:0 0 0 4px rgba(217,139,127,.2)}

@media (prefers-reduced-motion: reduce){
  .btn:hover,.card.hoverable:hover,.amen:hover{transform:none}
  .btn,.card,.amen{transition:none}
}

/* --- SCAN TO JOIN -------------------------------------------------------- */
.joinrow{display:flex;gap:30px;align-items:center;justify-content:center;
  flex-wrap:wrap;margin-top:40px;text-align:left}
.qrtile{margin:0;padding:14px;border-radius:20px;background:var(--surface);
  line-height:0;box-shadow:0 18px 40px -22px rgba(0,0,0,.55);flex:none}
.qrtile img{display:block;width:180px;height:180px}
.joincopy{max-width:34ch}
.joincopy h3{margin:0 0 8px;font-size:var(--step-h3)}
.joincopy p{margin:0 0 18px;opacity:.85}
.joincopy .btn{margin:0}
/* A code on the screen you are holding is not useful — on a phone the button is
   the whole answer, so the tile goes and the copy re-centres. */
@media(max-width:640px){
  .qrtile{display:none}
  .joinrow{text-align:center}
  .joincopy{max-width:none}
}

/* The Croma Favorite mark. Sits inline beside a product name on every surface
   — till, community app, website, admin list — so it reads the same way
   wherever a customer meets it. Rounded to match the source SVG's own corner
   radius, and nudged up so it sits on the text baseline rather than under it.
   Sits BEFORE the name, so the gap belongs on its right. */
.fav-mark{display:inline-block;border-radius:4px;vertical-align:-2px;
  margin-right:7px;flex:none}
