/* ===========================================================================
   InCode Label — "NOCTURNE / DAYLIGHT"
   ---------------------------------------------------------------------------
   A white-and-cyan site that goes dark in the places where going dark means
   something.

   The brief, in the owner's words: white and cyan is the main combination,
   with dark stretches in between, and the whole thing cinematic. Those two
   things sound like they fight. They do not — this is exactly how a good
   showroom is lit. The walls are white. The product sits under a lamp. Two
   or three moments in the room are deliberately in shadow so the lit things
   read as lit. A page that is dark everywhere has no contrast left to spend;
   a page that is white everywhere has no drama. This one alternates.

   THE ARCHITECTURE, and it is worth understanding before editing anything:

     The palette is a set of custom properties on :root — --paper, --ink,
     --line, --cyan and so on. Every component below is written in terms of
     those names and NEVER in terms of a literal colour.

     A dark band is then one thing only: an element that RE-DECLARES the
     same property names with dark values. Custom properties inherit, so
     every card, button, chip, input and heading inside that element picks
     up its dark form automatically, with not one duplicated rule and no
     `.card--dark` variants to keep in sync. Add `class="dark"` to a section
     and it becomes a cinematic band. Remove it and it is white again.

     There is one exception on purpose: --plate, the near-white surface that
     product photographs sit on, does NOT flip. A white label photographed
     on white must be shown on white in both modes, or the buyer cannot
     judge the stock. Inside a dark band that plate becomes a lit sample
     tray, which is the best the product has ever looked.

   THE RHYTHM as shipped:
     home        dark hero → white features → soft categories →
                 DARK gallery band → soft order band → dark footer
     inner pages white hero → white content → DARK closing band →
                 dark footer
     detail      white page, DARK order panel (the thing the page is for)
     contact     white form, DARK contact card beside it
     admin       light throughout — it is a desk, not a showroom.
                 See the note at the top of admin.html.

   Every class the pages and scripts rely on is preserved.
   ========================================================================= */

/* ── The daylight palette ────────────────────────────────────────────── */
:root{
  --paper:#FFFFFF;
  --soft:#F3F9FB;
  --soft-2:#E7F3F7;

  /* The plate. Deliberately NOT flipped by dark bands — see the note above.
     Not pure white either: a #FFF slab inside a dark band is a glare
     source, and this is the largest element on a product card. */
  --plate:#EFF6F8;
  --plate-2:#DAE8ED;

  --ink:#06171F;      /* headings                */
  --ink-2:#2E4550;    /* body copy               */
  --ink-3:#56727E;    /* secondary copy          */
  --muted:#6C8894;    /* captions, timestamps    */

  --line:#DCE9ED;
  --line-strong:#BCD6DE;

  --cyan:#0797AE;         /* the working ink                              */
  --cyan-ink:#046074;     /* cyan that must be READ on this ground        */
  --cyan-deep:#046074;
  --cyan-bright:#12C4DE;  /* cyan used as light                           */
  --cyan-light:#7FE6F5;
  --cyan-wash:#E6F8FB;

  /* Surfaces. Components reference these instead of picking a colour, so a
     dark band restyles all of them at once. */
  --card-bg:#FFFFFF;
  --card-bg-2:#FFFFFF;
  --card-border:var(--line);
  --field-bg:#FFFFFF;
  --chip-bg:var(--soft);
  --glass:none;

  /* The primary button. Ink-dark on white; it becomes a cyan lamp on dark. */
  --btn-bg:linear-gradient(180deg,#0D2531,#06171F);
  --btn-fg:#FFFFFF;
  --btn-border:transparent;
  --btn-shadow:0 12px 26px -16px rgba(6,23,31,.7);
  --btn-shadow-hover:0 18px 34px -16px rgba(6,23,31,.8);

  /* Text that sits ON a cyan fill. Cyan is a light hue: white on it fails
     contrast, so it is dark ink — the choice a road sign makes. */
  --on-cyan:#02171C;

  /* Glow is a token so daylight can switch it off entirely. Nothing on a
     white ground should be emitting light; that is what makes a light
     theme look cheap. */
  --glow:none;
  --glow-ring:none;
  --text-glow:none;

  --shadow:0 1px 2px rgba(6,23,31,.045), 0 12px 26px -18px rgba(6,23,31,.28);
  --shadow-lg:0 2px 5px rgba(6,23,31,.05), 0 30px 60px -32px rgba(6,23,31,.34);
  --shadow-cyan:0 14px 32px -16px rgba(7,151,174,.5);
  --ring:0 0 0 3px rgba(7,151,174,.24);

  /* admin.html consumes these four, so the names stay. */
  --grad:linear-gradient(90deg,var(--cyan-deep),var(--cyan));
  --grad-line:linear-gradient(90deg,transparent,var(--cyan-bright),transparent);
  --grad-ink:linear-gradient(165deg,#0E2531 0%,#08161E 55%,#050F15 100%);

  /* Film grain, at two strengths. This is the single ingredient that makes
     a large dark area read as a lit room rather than a flat rectangle. */
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.4'/%3E%3C/svg%3E");
  --grain-soft:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.09'/%3E%3C/svg%3E");

  --ease:cubic-bezier(.2,.7,.2,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-soft:cubic-bezier(.4,.1,.2,1);

  --font-display:'Roboto Condensed','Roboto',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-body:'Roboto',system-ui,-apple-system,'Segoe UI',Helvetica,Arial,sans-serif;
  --font-mono:ui-monospace,'SFMono-Regular',Menlo,Consolas,monospace;

  --radius-sm:4px;
  --radius:8px;
  --radius-lg:14px;
  --radius-xl:20px;

  --shell:1720px;
  --gut:clamp(20px,4.5vw,54px);

  /* Written by JavaScript at runtime; declared so the values a visitor sees
     with JS off are still deliberate ones.
       --mx / --my : the pointer inside a .has-spot band, as a percentage
       --i         : a word's place in the kinetic headline */
  --mx:50%;
  --my:50%;
  --i:0;
}

/* ── The dark bands ──────────────────────────────────────────────────
   ONE declaration block. Everything inside any of these elements — cards,
   buttons, inputs, chips, headings, hairlines — becomes its dark form
   because it was written against these names in the first place.

   To make a new section cinematic, add `class="dark"` to it in the HTML.
   That is the whole procedure. */
.hero,
.section.dark,
.order-panel,
.contact-note,
.chat-head,
footer{
  --paper:#0A1922;
  --soft:rgba(255,255,255,.055);
  --soft-2:rgba(255,255,255,.09);

  --ink:#FFFFFF;
  --ink-2:#A9C6D1;
  --ink-3:#8DAEBA;
  --muted:#7699A6;

  --line:rgba(127,230,245,.15);
  --line-strong:rgba(127,230,245,.32);

  --cyan:#12C4DE;
  --cyan-ink:#4EE2F5;      /* cyan text has to be brighter to be read here */
  --cyan-bright:#4EE2F5;
  --cyan-light:#9DEFFB;
  --cyan-wash:rgba(18,196,222,.12);

  --card-bg:linear-gradient(168deg,rgba(255,255,255,.075),rgba(255,255,255,.025));
  --card-bg-2:rgba(255,255,255,.05);
  --card-border:rgba(127,230,245,.15);
  --field-bg:rgba(255,255,255,.05);
  --chip-bg:rgba(255,255,255,.05);
  --glass:blur(14px);

  --btn-bg:linear-gradient(180deg,#4EE2F5,#12C4DE);
  --btn-fg:#02171C;
  --btn-border:rgba(157,239,251,.6);
  --btn-shadow:0 12px 38px -14px rgba(18,196,222,.75), 0 0 0 1px rgba(18,196,222,.3);
  --btn-shadow-hover:0 18px 54px -12px rgba(18,196,222,.9), 0 0 0 1px rgba(157,239,251,.55);

  --glow:0 0 60px -18px rgba(18,196,222,.5);
  --glow-ring:0 0 0 1px rgba(18,196,222,.28);
  --text-glow:0 0 22px rgba(18,196,222,.4);

  --shadow:0 1px 0 rgba(255,255,255,.05) inset, 0 20px 44px -28px rgba(0,0,0,.9);
  --shadow-lg:0 1px 0 rgba(255,255,255,.06) inset, 0 44px 96px -42px rgba(0,0,0,.95);
  --shadow-cyan:0 12px 44px -12px rgba(18,196,222,.6), 0 0 0 1px rgba(18,196,222,.35);
  --ring:0 0 0 3px rgba(18,196,222,.32);
}

/* The dark ground itself: grain on top, two cyan lights behind it, deep ink
   beneath. Written as one background stack rather than pseudo-elements,
   because several of these hosts already use ::before and ::after for the
   registration ticks, the seam and the corner marks. */
.hero,
.section.dark,
footer{
  background-color:#071219;
  background-image:
    var(--grain-soft),
    radial-gradient(1100px 620px at 82% -18%, rgba(18,196,222,.20), transparent 62%),
    radial-gradient(880px 560px at 4% 108%,  rgba(4,96,116,.34),  transparent 62%),
    linear-gradient(178deg,#0B1B24 0%,#071219 58%,#050E14 100%);
  background-size:160px 160px, auto, auto, auto;
  background-repeat:repeat, no-repeat, no-repeat, no-repeat;
  color:var(--ink-2);
}

/* ── Reset ───────────────────────────────────────────────────────────── */
*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;background:var(--paper)}
body{
  margin:0;background:var(--paper);color:var(--ink-2);
  font-family:var(--font-body);font-size:16.5px;line-height:1.75;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block}
a{color:var(--cyan-ink);text-decoration:none}
button{font:inherit}
:focus-visible{outline:2px solid var(--cyan);outline-offset:3px;border-radius:var(--radius-sm)}
::selection{background:rgba(7,151,174,.22)}

.container{width:min(var(--shell),100%);margin:0 auto;padding:0 var(--gut)}

h1,h2,h3,h4{
  font-family:var(--font-display);color:var(--ink);margin:0;font-weight:700;
  letter-spacing:-.025em;line-height:1.05;text-wrap:balance;
}
h1{font-size:clamp(38px,5.4vw,74px)}
h2{font-size:clamp(28px,3.6vw,48px)}
h3{font-size:clamp(18px,1.5vw,21px);letter-spacing:-.012em;line-height:1.3}

.lead{font-size:clamp(16.5px,1.35vw,19px);color:var(--ink-3);line-height:1.75;max-width:56ch;margin:20px 0 0}
.muted{color:var(--muted);font-size:15px;line-height:1.7}
.tiny{font-size:12.5px;color:var(--muted);line-height:1.6}
.small{font-size:13px;color:var(--muted);line-height:1.6}

/* On white the accent is flat printed ink. In a dark band --text-glow
   switches on and the same word becomes a light source. One rule, both
   behaviours — nothing on a white ground should be emitting light. */
.accent{color:var(--cyan);text-shadow:var(--text-glow)}

/* The verbatim contract: exactly what the admin typed, to the space. */
.verbatim{white-space:pre-wrap;overflow-wrap:break-word;word-break:break-word}

/* ── `hidden` must actually hide ─────────────────────────────────────
   The browser's own `[hidden] { display: none }` is the weakest rule there
   is, so ANY class that sets a display beats it. Several elements here are
   shown and hidden from JavaScript with `el.hidden = true` — the chat's
   unread badge, the phone-only order bar, the chat call row, the product
   card on the contact form, the detail-page eyebrow. Each one also carries
   a class that sets display, so each one stayed on screen while its script
   believed it was hidden. The unread badge sat there reading "0".

   This is the sweep that keeps that from happening again: whatever the
   class says, `hidden` wins. */
[hidden]{display:none !important}

/* ── Scroll progress ─────────────────────────────────────────────────── */
.scroll-rail{
  position:fixed;left:0;top:0;height:2px;width:100%;z-index:100;
  pointer-events:none;background:rgba(7,151,174,.08);
}
.scroll-rail i{
  display:block;height:100%;width:0;
  background:linear-gradient(90deg,var(--cyan-deep),#12C4DE);
}

/* ── The pointer light ───────────────────────────────────────────────
   Behind the words, never over them — a wash that tints text is the one
   thing a light must not do. Every host sets isolation:isolate, so this
   negative layer can never escape its own band. It is stronger inside a
   dark band, where there is room for it to be seen. */
.spotlight{
  position:absolute;inset:0;pointer-events:none;z-index:-1;
  opacity:0;transition:opacity .6s var(--ease);
  background:radial-gradient(480px circle at var(--mx,50%) var(--my,50%),
    rgba(7,151,174,.09), transparent 70%);
}
.hero .spotlight,.section.dark .spotlight,footer .spotlight{
  background:radial-gradient(520px circle at var(--mx,50%) var(--my,50%),
    rgba(18,196,222,.15), transparent 68%);
}
.has-spot:hover .spotlight{opacity:1}

/* ── Sections ────────────────────────────────────────────────────────
   Divided by registration ticks — the marks a press prints in the margin
   to line up a run. Borrowed from the customer's own product rather than
   invented as decoration. Under them, a light seam that brightens in the
   middle and fades at both ends. */
.section{padding:clamp(66px,7vw,108px) 0;position:relative;isolation:isolate}
.section.tight{padding:clamp(44px,5vw,70px) 0}
.section::before{
  content:"";position:absolute;left:0;right:0;top:0;height:8px;
  pointer-events:none;opacity:.45;
  background-image:repeating-linear-gradient(90deg,
    var(--line-strong) 0 1px, transparent 1px 34px);
  mask-image:linear-gradient(90deg,transparent,#000 16%,#000 84%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 16%,#000 84%,transparent);
}
.section + .section::after{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;
  pointer-events:none;background:var(--grad-line);opacity:.45;
}
.section.soft{background:var(--soft)}
/* A dark band paints its own ground (above), so it must not also inherit
   the soft wash, and its ticks need to be lit rather than printed. */
.section.dark.soft{background-image:
  var(--grain-soft),
  radial-gradient(1100px 620px at 82% -18%, rgba(18,196,222,.20), transparent 62%),
  radial-gradient(880px 560px at 4% 108%,  rgba(4,96,116,.34),  transparent 62%),
  linear-gradient(178deg,#0B1B24 0%,#071219 58%,#050E14 100%);
}

.section-head{
  display:flex;align-items:flex-end;justify-content:space-between;gap:28px;
  flex-wrap:wrap;margin-bottom:clamp(32px,4vw,54px);
}
.section-head h2{margin-top:12px}

/* An eyebrow is the plate number on a specimen sheet. */
.eyebrow{
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--font-mono);
  font-size:11px;font-weight:700;letter-spacing:.22em;text-transform:uppercase;
  color:var(--cyan-ink);
}
.eyebrow::before{content:"";width:18px;height:1px;flex:none;background:var(--cyan)}
.hero .eyebrow::before,.section.dark .eyebrow::before,footer .eyebrow::before{
  box-shadow:0 0 10px rgba(78,226,245,.9);
}

.eyebrow-pill{
  display:inline-flex;align-items:center;gap:10px;
  padding:7px 15px;border:1px solid var(--line-strong);
  border-radius:999px;background:var(--card-bg-2);
  font-family:var(--font-mono);
  font-size:10.5px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;
  color:var(--cyan-ink);
}
.eyebrow-pill::before{content:"";width:14px;height:1px;flex:none;background:var(--cyan)}
.hero .eyebrow-pill::before{box-shadow:0 0 10px rgba(78,226,245,.9)}

/* ── Buttons ─────────────────────────────────────────────────────────── */
.btn,.btn-call{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  padding:15px 28px;border-radius:var(--radius);border:1px solid transparent;
  font-family:var(--font-display);
  font-size:14.5px;font-weight:700;letter-spacing:.02em;
  cursor:pointer;text-align:center;position:relative;overflow:hidden;
  transition:background .24s var(--ease),color .24s var(--ease),
             border-color .24s var(--ease),box-shadow .3s var(--ease),
             transform .24s var(--ease);
}
/* A single sweep of light crosses the button on hover. One pass, not a
   loop — a loop is a novelty, a single pass is a material. */
.btn::after,.btn-call::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.28) 50%,transparent 70%);
  transform:translateX(-140%);
}
.btn:hover::after,.btn-call:hover::after{transition:transform .75s var(--ease-out);transform:translateX(140%)}

.btn.primary{background:var(--btn-bg);color:var(--btn-fg);border-color:var(--btn-border);box-shadow:var(--btn-shadow)}
.btn.primary:hover{transform:translateY(-2px);box-shadow:var(--btn-shadow-hover)}
.btn.ghost{
  background:var(--card-bg-2);color:var(--ink);border-color:var(--line-strong);
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
}
.btn.ghost:hover{border-color:var(--cyan);color:var(--cyan-ink);background:var(--cyan-wash)}
.btn.on-ink{background:transparent;color:var(--cyan-light);border-color:rgba(127,230,245,.38)}
.btn.on-ink:hover{background:rgba(127,230,245,.13);border-color:var(--cyan-bright);color:#fff}
.btn.block{width:100%}

.btn-call{
  background:var(--cyan-wash);color:var(--cyan-ink);
  border-color:var(--cyan);
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
}
.btn-call:hover{
  background:var(--cyan);color:#fff;border-color:var(--cyan);
  transform:translateY(-2px);box-shadow:var(--shadow-cyan);
}
.hero .btn-call:hover,.section.dark .btn-call:hover,footer .btn-call:hover{color:var(--on-cyan)}
.btn-call svg{flex:none}

/* ── Header ──────────────────────────────────────────────────────────
   Frosted white glass. It sits over a DARK hero on the home page and over
   white on every other page, which is why it is translucent rather than
   solid: it takes the colour of whatever is passing under it, and only
   commits to opaque white once you have scrolled far enough that there is
   real text underneath needing separation. */
.site-header{
  position:sticky;top:0;z-index:60;
  background:rgba(255,255,255,.72);
  backdrop-filter:blur(22px) saturate(180%);
  -webkit-backdrop-filter:blur(22px) saturate(180%);
  border-bottom:1px solid rgba(220,233,237,.7);
  transition:background .4s var(--ease),border-color .4s var(--ease),box-shadow .4s var(--ease);
}
.site-header.is-stuck{
  background:rgba(255,255,255,.94);
  border-bottom-color:var(--line-strong);
  box-shadow:0 14px 30px -26px rgba(6,23,31,.55);
}
.site-header .nav{display:flex;align-items:center;justify-content:space-between;gap:26px;height:76px}

/* The brand is the word. No mark anywhere on the site; the only picture
   identity is the browser-tab favicon. */
.brand{
  display:inline-flex;align-items:center;
  font-family:var(--font-display);
  font-size:24px;font-weight:700;letter-spacing:-.03em;color:var(--ink);
}
.brand .accent{color:var(--cyan)}

.site-header nav{display:flex;gap:2px;align-items:center}
.site-header nav a{
  position:relative;padding:10px 16px;border-radius:var(--radius-sm);
  font-family:var(--font-display);
  font-size:14.5px;font-weight:600;color:var(--ink-2);
  transition:color .22s var(--ease),background .22s var(--ease);
}
.site-header nav a::after{
  content:"";position:absolute;left:16px;right:16px;bottom:4px;height:2px;
  background:var(--cyan);transform:scaleX(0);transform-origin:left;
  transition:transform .32s var(--ease);
}
.site-header nav a:hover{color:var(--ink);background:rgba(7,151,174,.06)}
.site-header nav a:hover::after{transform:scaleX(1)}

.menu{
  display:none;width:42px;height:42px;border:1px solid var(--line-strong);
  border-radius:var(--radius);background:var(--paper);
  font-size:17px;color:var(--ink);cursor:pointer;line-height:1;
}

/* ── Hero — the one fully cinematic stage ────────────────────────────── */
.hero{
  position:relative;overflow:hidden;isolation:isolate;
  padding:clamp(74px,7.5vw,124px) 0 clamp(74px,7.5vw,124px);
}
.hero-bg{position:absolute;inset:0;z-index:-2;pointer-events:none;overflow:hidden}
/* A perspective floor grid fading up into the dark. It gives the hero a
   FLOOR, which is what makes the specimen card read as standing in a room
   rather than floating in a void. */
.hero-bg::before{
  content:"";position:absolute;inset:0;
  background-image:
    linear-gradient(rgba(127,230,245,.06) 1px,transparent 1px),
    linear-gradient(90deg,rgba(127,230,245,.06) 1px,transparent 1px);
  background-size:78px 78px;
  mask-image:radial-gradient(120% 92% at 50% 108%,#000 5%,transparent 72%);
  -webkit-mask-image:radial-gradient(120% 92% at 50% 108%,#000 5%,transparent 72%);
}
/* One slow shaft of light from the upper right, the way a single lamp falls
   across a studio. It drifts; it never visibly loops. */
.hero-bg::after{
  content:"";position:absolute;top:-40%;right:-10%;width:70%;height:180%;
  background:linear-gradient(200deg,rgba(18,196,222,.14),transparent 55%);
  transform:rotate(-14deg);filter:blur(38px);
  animation:beam 22s var(--ease-soft) infinite alternate;
}
@keyframes beam{
  from{opacity:.55;transform:rotate(-14deg) translateY(-2%)}
  to  {opacity:1;  transform:rotate(-10deg) translateY(3%)}
}

.orb{position:absolute;pointer-events:none;border-radius:50%;filter:blur(70px)}
.orb-cyan{
  left:-10%;bottom:-24%;width:min(54vw,620px);aspect-ratio:1;
  background:radial-gradient(circle,rgba(18,196,222,.28),transparent 66%);
  animation:breathe 15s var(--ease-soft) infinite alternate;
}
.orb-cyan-soft{
  right:-12%;top:-26%;width:min(48vw,560px);aspect-ratio:1;
  background:radial-gradient(circle,rgba(4,96,116,.40),transparent 68%);
  animation:breathe 19s var(--ease-soft) infinite alternate-reverse;
}
@keyframes breathe{
  from{transform:scale(1) translate3d(0,0,0);opacity:.75}
  to  {transform:scale(1.14) translate3d(2%,-3%,0);opacity:1}
}
/* Scan lines: a very faint horizontal rhythm over the hero only. This is
   the "film" in cinematic — almost invisible, and instantly missed if it
   were removed. */
.grid-lines{
  display:block;position:absolute;inset:0;z-index:-1;pointer-events:none;opacity:.5;
  background-image:repeating-linear-gradient(180deg,
    rgba(255,255,255,.026) 0 1px, transparent 1px 4px);
  mask-image:linear-gradient(180deg,transparent,#000 30%,#000 70%,transparent);
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 30%,#000 70%,transparent);
}

.hero-grid{
  display:grid;grid-template-columns:1.08fr .92fr;
  gap:clamp(36px,4.5vw,74px);align-items:center;
}
.hero h1{
  color:#fff;letter-spacing:-.035em;
  font-size:clamp(40px,5.6vw,76px);
  margin-top:26px;max-width:15ch;
}
.hero .lead{color:var(--ink-3);max-width:52ch}
.hero-actions{display:flex;gap:14px;flex-wrap:wrap;margin-top:36px}

/* Kinetic headline — each word rises once, in sequence. */
.kin{
  display:inline-block;overflow:hidden;vertical-align:bottom;
  /* The mask that hides a word before it rises is this box's own overflow,
     clipped exactly at the baseline — which shears the tail off every g, y
     and p. Pad down, then pull the same amount back out of the line box so
     the leading is untouched. */
  padding-bottom:.14em;margin-bottom:-.14em;
}
.kin > span{
  display:inline-block;transform:translateY(105%);opacity:0;
  transition:transform .9s var(--ease-out),opacity .7s var(--ease-out);
  transition-delay:calc(var(--i,0) * 58ms);
}
.kin-go .kin > span{transform:translateY(0);opacity:1}

/* The accent word in the hero, and the bloom behind it.
   The bloom has to hang on `.accent` and NOT on `.kin`, because .kin clips:
   its `overflow:hidden` is the mask the rising-word animation needs, and a
   wide text-shadow inside a clipping box does not fall off — it floods the
   box and paints a bright RECTANGLE around the word. A blurred radial on a
   sibling of that box falls off in every direction the way a real light
   does. `isolation:isolate` keeps the negative layer inside the word.
   The colour is re-stated on the split spans because background-clip and
   inherited colour do not both survive the extra nesting the split adds.

   NOTE the text-shadow is `none` here and the glow comes ONLY from the
   pseudo-element. Even a 22px shadow was enough to show its clipped edges:
   invisible on a desktop screen, a plainly visible cyan box around the word
   on a 2x phone. The bloom does the whole job. */
.hero h1 .accent{
  color:var(--cyan-bright);position:relative;isolation:isolate;
  text-shadow:none;
}
.hero h1 .accent::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  left:-6%;right:-6%;top:6%;bottom:14%;
  background:radial-gradient(closest-side,rgba(18,196,222,.42),transparent 78%);
  filter:blur(30px);
}
.hero h1 .accent .kin > span{color:var(--cyan-bright)}

/* The trust row reads as a materials list. */
.trust{display:flex;gap:0;flex-wrap:wrap;margin-top:40px;border-top:1px solid var(--line)}
.trust span{
  display:inline-flex;align-items:center;gap:9px;
  padding:16px 22px 0 0;margin-right:22px;
  font-family:var(--font-mono);
  font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-3);
}
.trust svg{color:var(--cyan-bright);filter:drop-shadow(0 0 6px rgba(18,196,222,.7))}

/* ── The specimen card — a label under a lamp ────────────────────────── */
.hero-card{position:relative;isolation:isolate}
.hero-glow{
  position:absolute;inset:-14%;z-index:-1;pointer-events:none;
  background:radial-gradient(circle at 50% 45%,rgba(18,196,222,.34),transparent 62%);
  filter:blur(46px);
  animation:breathe 12s var(--ease-soft) infinite alternate;
}
.label-demo{
  position:relative;
  background:linear-gradient(165deg,rgba(255,255,255,.11),rgba(255,255,255,.035));
  border:1px solid var(--line-strong);border-radius:var(--radius-lg);
  padding:28px 26px 24px;
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  box-shadow:var(--shadow-lg), 0 0 0 1px rgba(255,255,255,.04) inset;
  transform:perspective(1400px) rotateY(-5deg) rotateX(2deg);
  transition:transform .8s var(--ease-out);
}
.hero-card:hover .label-demo{transform:perspective(1400px) rotateY(0deg) rotateX(0deg)}
/* Corner registration marks — the press mark, here as a lit edge. */
.label-demo::before,.label-demo::after{
  content:"";position:absolute;width:16px;height:16px;pointer-events:none;
  border:1px solid var(--cyan-bright);box-shadow:0 0 12px rgba(18,196,222,.7);
}
.label-demo::before{top:-1px;left:-1px;border-right:0;border-bottom:0;border-top-left-radius:var(--radius-lg)}
.label-demo::after{bottom:-1px;right:-1px;border-left:0;border-top:0;border-bottom-right-radius:var(--radius-lg)}

.label-demo .tiny{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  font-family:var(--font-mono);font-size:10.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--cyan-light);font-weight:700;
}
.sku-chip{
  padding:4px 10px;border:1px solid rgba(18,196,222,.5);border-radius:999px;
  color:var(--cyan-bright);font-size:9.5px;letter-spacing:.16em;
  background:rgba(18,196,222,.1);
}
/* A real barcode — black on WHITE, because that is the only way a barcode
   exists. Bars on the dark card would have been the prettier lie; no
   scanner would read it, and neither would a buyer who knows the trade. So
   it gets its own lit plate. */
.barcode-real{
  position:relative;overflow:hidden;
  height:104px;margin:22px 0 16px;border-radius:var(--radius-sm);
  background-color:#F7FBFC;
  background-image:repeating-linear-gradient(90deg,
    #06131A 0 2px, #F7FBFC 2px 5px, #06131A 5px 6px, #F7FBFC 6px 11px,
    #06131A 11px 14px, #F7FBFC 14px 16px, #06131A 16px 17px, #F7FBFC 17px 23px);
  box-shadow:0 0 34px -6px rgba(18,196,222,.45), 0 10px 30px -14px rgba(0,0,0,.9);
}
/* A slow scanner sweep across the barcode — the one animation on the whole
   page that is not just atmosphere, it is the product doing its job. */
.barcode-real::after{
  content:"";position:absolute;inset:0;width:46%;
  background:linear-gradient(100deg,transparent,rgba(18,196,222,.55) 45%,rgba(255,255,255,.5) 50%,rgba(18,196,222,.55) 55%,transparent);
  mix-blend-mode:screen;transform:translateX(-140%);
  animation:barcodeScan 4.6s cubic-bezier(.5,0,.25,1) infinite;
}
@keyframes barcodeScan{
  0%,58%{transform:translateX(-140%)}
  86%,100%{transform:translateX(240%)}
}
@media (prefers-reduced-motion: reduce){ .barcode-real::after{animation:none;display:none} }
.sku{
  font-family:var(--font-mono);font-size:11px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--ink-2);font-weight:700;text-align:center;
}

/* ── Page hero — white, with the cyan light kept low ─────────────────── */
.page-hero{
  position:relative;overflow:hidden;isolation:isolate;
  padding:clamp(54px,6vw,92px) 0 clamp(38px,4vw,58px);
  background:var(--paper);
}
.page-hero::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(900px 420px at 84% -34%, rgba(7,151,174,.13), transparent 62%),
    linear-gradient(rgba(7,151,174,.05) 1px,transparent 1px),
    linear-gradient(90deg,rgba(7,151,174,.05) 1px,transparent 1px);
  background-size:auto, 78px 78px, 78px 78px;
  mask-image:linear-gradient(180deg,#000,transparent 86%);
  -webkit-mask-image:linear-gradient(180deg,#000,transparent 86%);
}
.page-hero h1{margin-top:20px;font-size:clamp(33px,4.4vw,58px)}
.page-hero .lead{margin-top:16px}
/* An inner page's hero already ends in generous space; the section after it
   was adding a full pad on top, opening a hole about 200px tall between the
   sentence and the first thing you can click. */
.page-hero + .section{padding-top:clamp(38px,4vw,62px)}

.breadcrumb{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-family:var(--font-mono);font-size:11.5px;letter-spacing:.07em;
  color:var(--muted);margin-bottom:28px;
}
.breadcrumb a{color:var(--cyan-ink);font-weight:700}
.breadcrumb span{color:var(--line-strong)}

/* ── Cards ───────────────────────────────────────────────────────────
   White sheets with a hairline on the light pages; panes of smoked glass
   inside a dark band. Same rule, both results — see --card-bg. */
.feature-card,.category-card,.product-card,.cta-band-inner,.pf-stat,.gallery-card,.inq-card{
  background:var(--card-bg);border:1px solid var(--card-border);
  border-radius:var(--radius-lg);
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
}

.feature-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(238px,1fr));gap:16px}
.feature-card{
  padding:30px 28px 32px;position:relative;overflow:hidden;
  transition:border-color .3s var(--ease),transform .3s var(--ease),box-shadow .3s var(--ease);
}
/* The lit cap: a short bar on the top edge that grows to the full width of
   the card when you point at it. */
.feature-card::before{
  content:"";position:absolute;left:0;top:0;height:2px;width:34px;
  background:var(--cyan);transition:width .45s var(--ease-out);
}
.feature-card:hover{
  border-color:var(--line-strong);transform:translateY(-3px);
  box-shadow:var(--shadow),var(--glow);
}
.feature-card:hover::before{width:100%}
.feature-card h3{margin-bottom:10px}

.category-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));gap:16px}
.category-card{
  display:block;padding:28px 26px 30px;position:relative;overflow:hidden;
  transition:border-color .3s var(--ease),transform .3s var(--ease),box-shadow .3s var(--ease);
}
.category-card::after{
  content:"→";position:absolute;right:24px;bottom:24px;
  font-size:18px;color:var(--cyan);opacity:0;transform:translateX(-8px);
  transition:opacity .28s var(--ease),transform .28s var(--ease);
}
.category-card:hover{
  border-color:var(--cyan);transform:translateY(-3px);
  box-shadow:var(--shadow),var(--glow);
}
.category-card:hover::after{opacity:1;transform:none}
.category-card h3{color:var(--ink);margin-bottom:8px}

/* ── Products ────────────────────────────────────────────────────────── */
.category-tabs,.portfolio-tabs{display:flex;gap:9px;flex-wrap:wrap;margin-bottom:32px}
.tab-pill{
  padding:10px 19px;border:1px solid var(--line-strong);border-radius:999px;
  background:var(--card-bg-2);color:var(--ink-2);cursor:pointer;
  font-family:var(--font-display);font-size:13.5px;font-weight:600;
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
  transition:.24s var(--ease);
}
.tab-pill:hover{border-color:var(--cyan);color:var(--cyan-ink);background:var(--cyan-wash)}
.tab-pill.active{background:var(--btn-bg);border-color:var(--btn-border);color:var(--btn-fg);box-shadow:var(--btn-shadow)}

/* Four per row on desktop (was three) — narrower cards, so gap tightens a
   touch to keep them from feeling cramped. auto-fit rather than auto-fill:
   a half-empty last row of an odd product count stretches to fill the
   width instead of leaving a phantom empty column. The three breakpoints
   below step it down to 3 / 2 / 1 rather than letting minmax() reflow it
   unpredictably at in-between widths. */
/* --products-per-row is set on the #productGrid element by app.js from the
   admin's Settings choice (falls back to 4 if JS hasn't run yet). The
   breakpoints below still narrow the grid on smaller screens regardless of
   that choice, so it never gets cramped on tablet/mobile. */
.product-grid{display:grid;grid-template-columns:repeat(var(--products-per-row,4),1fr);gap:18px}
@media (max-width:1180px){.product-grid{grid-template-columns:repeat(min(var(--products-per-row,4),3),1fr)}}
@media (max-width:820px){.product-grid{grid-template-columns:repeat(min(var(--products-per-row,4),2),1fr)}}
@media (max-width:520px){.product-grid{grid-template-columns:1fr}}
.product-card{
  display:flex;flex-direction:column;overflow:hidden;
  transition:border-color .3s var(--ease),box-shadow .3s var(--ease),transform .3s var(--ease);
}
.product-card:hover{
  border-color:var(--cyan);transform:translateY(-4px);
  box-shadow:var(--shadow-lg),var(--glow);
}

/* THE PLATE.
   Product photographs in this trade are white labels on white backgrounds.
   The plate is near-white in BOTH modes and does not flip with the band —
   on a white page it is a quiet tray, inside a dark band it becomes a lit
   sample tray, and in both cases the buyer sees the true colour of the
   stock, which is the one thing a label photo is for.
   object-fit:contain, always: the whole label shows, never cropped. */
.product-image{
  display:grid;place-items:center;aspect-ratio:4/3;
  background:transparent;
  border-bottom:1px solid var(--card-border);padding:18px;position:relative;
}
/* The lamp falls from the upper left, so the lower right of the plate is
   where it runs out. One inset shadow there is the whole trick. */
.product-image::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  box-shadow:inset -14px -18px 40px -30px rgba(3,8,11,.7);
}
.product-image img{width:100%;height:100%;object-fit:contain;transition:transform .6s var(--ease-epic)}
.product-card:hover .product-image img{transform:scale(1.06)}
.product-placeholder{display:grid;place-items:center;width:100%;height:100%;font-size:36px;color:#B7CBD2}
.product-body{padding:22px 24px 24px;display:flex;flex-direction:column;gap:10px;flex:1}
.product-body h3 a{color:var(--ink)}
.product-body h3 a:hover{color:var(--cyan-ink)}
.product-body .card-call{margin-top:auto}

.price-row{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.price{
  font-family:var(--font-display);font-size:27px;font-weight:700;
  letter-spacing:-.025em;color:var(--ink);font-variant-numeric:tabular-nums;
}
.price-note{font-size:12.5px;color:var(--muted)}
/* The unit badge — Pcs / Roll / Yds / Set / Dzn — set from the admin's
   fixed dropdown, never free-typed, so it reads identically on every
   product. Sits right after the price in every price-row on the site. */
.price-unit{
  display:inline-flex;align-items:center;padding:3px 10px;border-radius:999px;
  background:var(--cyan-wash);border:1px solid var(--line-strong);
  font-family:var(--font-mono);font-size:11px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:var(--cyan-ink);
}
.price-ask{
  font-family:var(--font-display);font-size:16px;font-weight:700;color:var(--cyan-ink);
  display:inline-flex;align-items:center;gap:6px;transition:color .2s var(--ease);
}
.price-ask::after{content:"→";transition:transform .24s var(--ease)}
.price-ask:hover{color:var(--cyan-bright)}
.price-ask:hover::after{transform:translateX(3px)}

.spec-chips{display:flex;gap:7px;flex-wrap:wrap}
.spec-chips span{
  padding:5px 11px;border:1px solid var(--line);border-radius:999px;
  background:var(--chip-bg);
  font-family:var(--font-mono);font-size:11px;color:var(--ink-3);
}

.card-call{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:12px 17px;border-radius:var(--radius);
  background:var(--cyan-wash);border:1px solid var(--cyan);color:var(--cyan-ink);
  font-family:var(--font-display);font-size:13.5px;font-weight:700;
  transition:.24s var(--ease);
}
.card-call:hover{background:var(--cyan);color:#fff;box-shadow:var(--shadow-cyan)}
.section.dark .card-call:hover{color:var(--on-cyan)}

/* ── Card action row (Call + WhatsApp side by side, always in one line —
   never wrap the second button under the first, even on the narrowest
   card in a 4-up desktop grid). Each button shares the row equally and is
   allowed to shrink below its own text width (min-width:0), with a
   slightly tighter size than the standalone buttons elsewhere so both
   labels keep fitting comfortably. ──────────────────────────────────── */
.card-actions{display:flex;gap:8px;flex-wrap:nowrap;margin-top:auto}
.card-actions .card-call{margin-top:0}
.card-actions .card-call,
.card-actions .card-whatsapp{
  flex:1 1 0;min-width:0;
  padding:11px 10px;gap:6px;
  font-size:12.5px;
}
.card-actions .card-call svg,
.card-actions .card-whatsapp svg{width:14px;height:14px;flex:none}
.card-actions .card-call .call-slide{min-width:0;width:100%}

/* ── WhatsApp order/inquiry button ───────────────────────────────────── */
/* A deliberately quieter, more restrained green than WhatsApp's own bright
   brand color — it sits next to the cyan Call button without fighting it,
   and reads as one more premium action rather than a third-party badge. */
.btn-whatsapp,.card-whatsapp{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:12px 17px;border-radius:var(--radius);
  background:rgba(19,145,86,.08);border:1px solid rgba(19,145,86,.55);color:#0F7A46;
  font-family:var(--font-display);font-size:13.5px;font-weight:700;
  transition:.24s var(--ease);white-space:nowrap;
}
.btn-whatsapp:hover,.card-whatsapp:hover{background:#128C4A;color:#fff;border-color:#128C4A;box-shadow:0 10px 24px -12px rgba(18,140,74,.55)}
.section.dark .btn-whatsapp,.section.dark .card-whatsapp{color:#4FE39B;border-color:rgba(79,227,155,.4);background:rgba(79,227,155,.08)}
.section.dark .btn-whatsapp:hover,.section.dark .card-whatsapp:hover{background:#17A85B;color:#04180E;border-color:#17A85B}

/* ── Stock status badge ──────────────────────────────────────────────── */
.stock-badge{
  display:inline-block;padding:4px 11px;border-radius:999px;
  font-family:var(--font-display);font-size:10.5px;font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;vertical-align:middle;white-space:nowrap;max-width:none;
}
.stock-ready{background:rgba(15,122,70,.1);color:#0F7A46;border:1px solid rgba(15,122,70,.35)}
.stock-limited{background:rgba(184,134,11,.12);color:#8A6200;border:1px solid rgba(184,134,11,.4)}
.stock-out{background:rgba(192,57,43,.1);color:#B02A24;border:1px solid rgba(192,57,43,.35)}
.product-image .stock-badge{position:absolute;top:12px;right:12px;z-index:2;backdrop-filter:blur(10px) saturate(160%);background:rgba(255,255,255,.86)}
h1 .stock-badge{margin-left:12px;vertical-align:middle;transform:translateY(-4px)}

/* ── Product detail ──────────────────────────────────────────────────── */
.product-detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(30px,4vw,62px);align-items:start}
.product-detail-image{
  display:grid;place-items:center;aspect-ratio:1;padding:28px;position:relative;
  background:transparent;
  border:1px solid var(--line-strong);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-lg);
}
.product-detail-image::before,.product-detail-image::after{
  content:"";position:absolute;width:17px;height:17px;border:1px solid var(--cyan);opacity:.8;
}
.product-detail-image::before{top:-1px;left:-1px;border-right:0;border-bottom:0}
.product-detail-image::after{bottom:-1px;right:-1px;border-left:0;border-top:0}
.product-detail-image img{width:100%;height:100%;object-fit:contain}
.product-detail h1{margin:16px 0 0;font-size:clamp(29px,3.4vw,46px)}

.detail-desc{
  margin:26px 0 0;padding:22px 24px;
  background:var(--soft);border:1px solid var(--line);
  border-radius:var(--radius-lg);border-left:2px solid var(--cyan);
}
.detail-desc-head{
  display:block;font-family:var(--font-mono);
  font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--cyan-ink);font-weight:700;margin-bottom:11px;
}
.detail-desc .verbatim{color:var(--ink-2);font-size:15.5px;line-height:1.8}

/* The order panel is a dark band on a white page — the thing the whole page
   exists for, lit like the hero. */
.order-panel{
  margin-top:28px;padding:28px;border-radius:var(--radius-lg);
  background:var(--grad-ink);color:var(--ink-2);position:relative;overflow:hidden;
  border:1px solid rgba(127,230,245,.22);
  box-shadow:var(--shadow-lg), 0 0 60px -28px rgba(18,196,222,.5);
}
.order-panel::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--grad-line)}
/* A soft light in the corner, so the price sits in a pool of it rather than
   on a flat rectangle. */
.order-panel::after{
  content:"";position:absolute;right:-20%;top:-60%;width:60%;height:180%;pointer-events:none;
  background:radial-gradient(circle,rgba(18,196,222,.18),transparent 62%);filter:blur(30px);
}
.order-panel > *{position:relative;z-index:1}
.order-label{
  display:block;font-family:var(--font-mono);
  font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--cyan-bright);font-weight:700;
}
.order-price{
  font-family:var(--font-display);font-size:clamp(34px,3.8vw,50px);font-weight:700;
  letter-spacing:-.03em;color:#fff;margin-top:8px;font-variant-numeric:tabular-nums;
  text-shadow:0 0 50px rgba(18,196,222,.35);
}
/* Call + WhatsApp always sit together on their own first line (equal
   width, never one above the other); the "Send an enquiry" link — a
   longer label, and a different action — gets its own full-width line
   underneath rather than fighting the other two for space. */
.order-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:22px}
.order-actions .btn-call,
.order-actions .btn-whatsapp{flex:1 1 0;min-width:0}
.order-actions .btn-call .call-slide{min-width:0;width:100%}
.order-actions .btn.on-ink{flex:1 1 100%}
.order-hint{font-size:13px;color:var(--muted);margin:16px 0 0;line-height:1.65}
.order-price .price-unit{
  background:rgba(18,196,222,.14);border-color:rgba(18,196,222,.42);color:var(--cyan-bright);
  vertical-align:middle;letter-spacing:.04em;
}

/* ── The sliding number ──────────────────────────────────────────────── */
.call-slide{position:relative;display:grid;overflow:hidden;align-items:center;justify-items:start}
.call-slide > span{grid-area:1/1;white-space:nowrap;transition:transform .44s var(--ease),opacity .34s var(--ease)}
.call-number,.call-copied{transform:translateY(115%);opacity:0}
.call-number{font-variant-numeric:tabular-nums;letter-spacing:.03em}
.is-revealed .call-slide .call-label{transform:translateY(-115%);opacity:0}
.is-revealed .call-slide .call-number{transform:translateY(0);opacity:1}
.is-copied .call-slide .call-number{transform:translateY(-115%);opacity:0}
.is-copied .call-slide .call-copied{transform:translateY(0);opacity:1}

/* ── CTA bands ───────────────────────────────────────────────────────── */
.cta-band-inner{
  display:flex;align-items:center;justify-content:space-between;gap:30px;
  flex-wrap:wrap;padding:clamp(32px,3.8vw,50px);position:relative;
  isolation:isolate;overflow:hidden;border-color:var(--line-strong);
}
.cta-band-inner::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(700px 300px at 8% 122%,var(--cyan-wash),transparent 62%);
}
.cta-band-inner::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;
  background:linear-gradient(180deg,transparent,var(--cyan),transparent);
}
.section.dark .cta-band-inner::after{box-shadow:0 0 20px rgba(18,196,222,.8)}
.cta-band-inner > *{position:relative;z-index:1}

/* ── Gallery ─────────────────────────────────────────────────────────── */
.pf-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:14px;margin-bottom:34px}
.pf-stat{padding:24px 26px;position:relative;overflow:hidden}
.pf-stat::before{
  content:"";position:absolute;left:0;top:0;height:2px;width:100%;
  background:var(--grad-line);opacity:.8;
}
.pf-stat strong{
  display:block;font-family:var(--font-display);font-size:34px;font-weight:700;
  letter-spacing:-.035em;color:var(--ink);
}
.pf-stat span{
  display:block;font-family:var(--font-mono);font-size:10.5px;
  letter-spacing:.18em;text-transform:uppercase;color:var(--muted);
  font-weight:700;margin-top:6px;
}

.gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(292px,1fr));gap:18px}
.gallery-card{
  overflow:hidden;display:flex;flex-direction:column;
  transition:border-color .3s var(--ease),box-shadow .3s var(--ease),transform .3s var(--ease);
}
.gallery-card:hover{border-color:var(--cyan);transform:translateY(-3px);box-shadow:var(--shadow-lg),var(--glow)}
/* Same plate as the product cards, same reason. */
.gallery-card img{
  width:100%;aspect-ratio:4/3;object-fit:contain;
  background:transparent;
  border-bottom:1px solid var(--card-border);padding:16px;
}
.gallery-cap{padding:18px 20px 20px;display:flex;flex-direction:column;gap:8px;font-size:14px;color:var(--ink-2)}
.pf-tag{
  align-self:flex-start;padding:4px 11px;
  border:1px solid var(--cyan);border-radius:999px;background:var(--cyan-wash);
  font-family:var(--font-mono);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--cyan-ink);font-weight:700;
}

/* ── Contact ─────────────────────────────────────────────────────────── */
.contact-grid{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(28px,4vw,58px);align-items:start}
.contact-note{
  padding:30px 28px;border-radius:var(--radius-lg);
  background:var(--grad-ink);color:var(--ink-2);position:relative;overflow:hidden;
  border:1px solid rgba(127,230,245,.22);
  box-shadow:var(--shadow-lg), 0 0 60px -30px rgba(18,196,222,.5);
}
.contact-note::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--grad-line)}
.contact-note::after{
  content:"";position:absolute;left:-25%;bottom:-60%;width:80%;height:150%;pointer-events:none;
  background:radial-gradient(circle,rgba(18,196,222,.16),transparent 62%);filter:blur(34px);
}
.contact-note > *{position:relative;z-index:1}
.contact-note strong{
  display:block;font-family:var(--font-mono);font-size:10.5px;
  letter-spacing:.22em;text-transform:uppercase;color:var(--cyan-bright);
}
.contact-note > span{display:block;margin-top:12px;font-size:14.5px;line-height:1.75;color:var(--ink-3)}
.contact-channels{display:flex;flex-direction:column;gap:11px;margin-top:24px}
.contact-channel{
  display:flex;align-items:center;gap:14px;padding:14px 16px;
  border:1px solid var(--line);border-radius:var(--radius);
  background:rgba(255,255,255,.035);
  transition:background .24s var(--ease),border-color .24s var(--ease),transform .24s var(--ease);
}
.contact-channel:hover{background:rgba(18,196,222,.11);border-color:rgba(18,196,222,.45);transform:translateX(3px)}
.cc-icon{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  border:1px solid rgba(18,196,222,.35);border-radius:var(--radius-sm);
  background:rgba(18,196,222,.09);color:var(--cyan-bright);
}
.cc-text{display:flex;flex-direction:column;min-width:0}
.cc-text small{font-family:var(--font-mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.cc-text b{color:#fff;font-size:15px;word-break:break-all}

.contact-form{display:flex;flex-direction:column;gap:18px}
.contact-form > label{
  display:flex;flex-direction:column;gap:9px;
  font-family:var(--font-display);font-size:13.5px;font-weight:600;color:var(--ink-2);
}
.contact-form input,.contact-form textarea{
  padding:15px 16px;border-radius:var(--radius);
  border:1px solid var(--line-strong);background:var(--field-bg);
  font-size:15.5px;color:var(--ink);font-family:var(--font-body);
  transition:border-color .24s var(--ease),box-shadow .24s var(--ease);
}
.contact-form input::placeholder,.contact-form textarea::placeholder{color:var(--muted)}
.contact-form input:focus,.contact-form textarea:focus{outline:none;border-color:var(--cyan);box-shadow:var(--ring)}
.contact-form textarea{resize:vertical;min-height:150px;line-height:1.75}
.form-status{font-size:14px;color:var(--cyan-ink);min-height:1.2em}

/* ---- Incode Label AI — inquiry writer on the Contact form ---- */
.ai-writer{
  border:1px solid var(--line-strong);border-radius:var(--radius);padding:16px 18px;display:grid;gap:10px;
  background:
    radial-gradient(420px 200px at 100% 0%, rgba(6,188,214,.10), transparent 62%),
    linear-gradient(180deg,var(--cyan-wash),var(--field-bg));
}
.ai-writer-head strong{display:block;font-family:var(--font-display);font-size:14px;letter-spacing:-.02em;color:var(--ink)}
.ai-writer-head .small{display:block;margin-top:3px;color:var(--ink-3);font-size:12.5px}
.ai-writer-row{display:flex;gap:8px;flex-wrap:wrap}
.ai-writer-row .btn{font-size:13px;white-space:nowrap;padding:9px 16px}
.ai-writer-row .btn:disabled{opacity:.5;cursor:not-allowed}
.ai-writer-row .btn[data-ai-lang].is-active{border-color:var(--cyan);color:var(--cyan-ink);box-shadow:var(--ring)}
.ai-writer p{margin:0;font-size:12.5px;color:var(--ink-3)}

/* The honeypot: out of the layout and out of the accessibility tree, but
   NOT display:none and NOT type=hidden — the bots worth catching skip both
   of those. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* "You are asking about this product" */
#inquiryProduct[hidden]{display:none}
.inq-card{display:grid;grid-template-columns:108px 1fr;gap:18px;align-items:center;padding:16px}
.inq-thumb{
  display:grid;place-items:center;width:108px;height:108px;
  border:1px solid var(--line);border-radius:var(--radius);
  background:linear-gradient(168deg,#F8FCFD,var(--plate-2));overflow:hidden;
}
.inq-thumb img{width:100%;height:100%;object-fit:contain}
.inq-body h3{margin:8px 0 0;font-size:18px}
.inq-body h3 a{color:var(--ink)}
.inq-body h3 a:hover{color:var(--cyan-ink)}
.inq-body .price-row{margin-top:8px}
.inq-body .tiny{margin-top:9px}
@media (max-width:560px){
  .inq-card{grid-template-columns:1fr}
  .inq-thumb{width:100%;height:auto;aspect-ratio:4/3}
}

/* "Write with InCode Label AI" — sits under the Description textarea,
   only shown once a Subject has been typed (see app.js). */
.ai-write-btn{
  align-self:flex-start;display:inline-flex;align-items:center;gap:8px;
  padding:9px 16px;border-radius:999px;border:1px solid var(--cyan);
  background:var(--cyan-wash);color:var(--cyan-ink);font-size:13px;font-weight:700;
  font-family:var(--font-display);cursor:pointer;
  transition:background .22s var(--ease),color .22s var(--ease);
}
.ai-write-btn:hover{background:var(--cyan);color:#fff}
.ai-write-btn:disabled{opacity:.55;cursor:default}
.ai-write-btn svg{flex:none}
.ai-write-status{margin-top:-2px}

/* ── Sticky order bar (phones) ───────────────────────────────────────── */
.order-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:80;display:none;
  align-items:center;justify-content:space-between;gap:14px;
  padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  background:rgba(255,255,255,.94);
  backdrop-filter:blur(20px) saturate(160%);-webkit-backdrop-filter:blur(20px) saturate(160%);
  border-top:1px solid var(--line-strong);
  box-shadow:0 -14px 30px -24px rgba(6,23,31,.6);
}
.ob-label{
  font-family:var(--font-mono);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);font-weight:700;
}
.ob-price{font-family:var(--font-display);font-size:21px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}

/* ── Footer — the page closes in the dark ────────────────────────────── */
footer{
  position:relative;overflow:hidden;isolation:isolate;
  padding:74px 0 0;
}
footer::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--grad-line);opacity:.8}
/* One last pool of light, so the document ends on the accent rather than
   fading into nothing. */
footer::after{
  content:"";position:absolute;left:50%;bottom:-58%;width:90%;height:120%;
  transform:translateX(-50%);pointer-events:none;z-index:-1;
  background:radial-gradient(circle,rgba(18,196,222,.15),transparent 62%);filter:blur(46px);
}
.footer-grid{display:grid;grid-template-columns:1.7fr 1fr 1fr;gap:44px;padding-bottom:48px}
.footer-grid .brand{color:#fff;margin-bottom:18px}
.footer-grid .brand .accent{color:var(--cyan-bright)}
.footer-grid p{font-size:14.5px;line-height:1.8;color:var(--ink-3);max-width:44ch;margin:0}
.footer-grid strong{
  display:block;font-family:var(--font-mono);font-size:10.5px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--muted);margin-bottom:14px;
}
.footer-grid > div > a{
  display:block;padding:6px 0;color:var(--ink-2);font-size:14.5px;
  transition:color .22s var(--ease),transform .22s var(--ease);
}
.footer-grid > div > a:hover{color:var(--cyan-bright);transform:translateX(3px)}
.footer-contact{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:12px}
.footer-contact a{display:inline-flex;align-items:center;gap:10px;color:#fff;font-weight:700;font-size:15px}
.footer-contact a:hover{color:var(--cyan-bright)}
.footer-bottom{
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:20px 0 24px;border-top:1px solid var(--line);
  font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--muted);
}
/* The chat bubble is fixed over the bottom-right corner and the last line
   of the footer ran straight underneath it. Leave it the room it takes —
   60px of bubble, 24px of offset, and a gap. */
.footer-bottom > :last-child{padding-right:96px}
@media (max-width:760px){ .footer-bottom > :last-child{padding-right:0} }

/* ── Reveal on scroll ────────────────────────────────────────────────
   CONTENT IS VISIBLE BY DEFAULT. The hiding is gated behind the `js` class,
   which a two-line inline script in every page's <head> adds before the
   first paint. `.in-view` is only ever added by app.js, so hiding by
   default would leave the whole page blank if that file never ran —
   JavaScript off, an ad-blocker, one bad upload. `.reveal-all` is the same
   script's backstop when nothing has been revealed after a few seconds. */
.js .reveal{
  opacity:0;transform:translateY(20px);
  transition:opacity .8s var(--ease-out),transform .8s var(--ease-out);
}
.reveal.in-view,.reveal-all .reveal{opacity:1;transform:none}
.reveal:nth-child(2){transition-delay:.07s}
.reveal:nth-child(3){transition-delay:.14s}
.reveal:nth-child(4){transition-delay:.21s}

/* Loading skeletons — the shape of what is coming, so nothing jumps. */
.skeleton{
  border-radius:var(--radius-lg);border:1px solid var(--line);
  background:linear-gradient(100deg,var(--soft) 30%,var(--paper) 50%,var(--soft) 70%);
  background-size:220% 100%;animation:shimmer 1.6s linear infinite;min-height:240px;
}
.section.dark .skeleton{
  background:linear-gradient(100deg,rgba(255,255,255,.04) 30%,rgba(18,196,222,.11) 50%,rgba(255,255,255,.04) 70%);
  background-size:220% 100%;
}
@keyframes shimmer{from{background-position:140% 0}to{background-position:-40% 0}}
.skeleton.sk-card{min-height:300px}
.skeleton.sk-detail{min-height:420px;grid-column:1/-1}
.skeleton.sk-inquiry{min-height:136px;margin-bottom:20px}
@media (prefers-reduced-motion: reduce){
  .skeleton{animation:none;background:var(--soft)}
}

/* ── Chat widget ─────────────────────────────────────────────────────
   The widget is a POSITIONING SHELL, not a surface. The closed panel keeps
   its layout box, which stretches this container to roughly 376x550 — an
   invisible slab over the right-hand third of every page. Left hit-testable
   it silently ate clicks on whatever sat underneath: a Call For Order
   button, the right column of product cards, footer links. So the shell
   passes every pointer straight through, and only the two things really
   there take clicks back. */
.chat-widget{
  position:fixed;right:24px;bottom:24px;z-index:90;
  display:flex;flex-direction:column;align-items:flex-end;gap:14px;
  pointer-events:none;
}
.chat-bubble{pointer-events:auto}
.chat-panel.open{pointer-events:auto}
.chat-whatsapp-fab{pointer-events:auto}

.chat-whatsapp-fab{
  width:48px;height:48px;border-radius:var(--radius-lg);
  background:#25D366;color:#fff;
  display:grid;place-items:center;
  box-shadow:0 10px 24px -10px rgba(18,140,74,.6);
  transition:transform .26s var(--ease),box-shadow .3s var(--ease);
}
.chat-whatsapp-fab:hover{transform:translateY(-3px) scale(1.03);box-shadow:0 14px 30px -10px rgba(18,140,74,.75)}
.chat-whatsapp-fab svg{display:block}

.chat-bubble{
  position:relative;width:60px;height:60px;border-radius:var(--radius-lg);
  border:1px solid var(--cyan-deep);cursor:pointer;
  background:linear-gradient(180deg,#12C4DE,#0797AE);
  color:#fff;font-size:24px;line-height:1;
  display:grid;place-items:center;box-shadow:var(--shadow-cyan);
  transition:transform .26s var(--ease),box-shadow .3s var(--ease);
}
.chat-bubble:hover{transform:translateY(-3px) scale(1.03);box-shadow:0 18px 46px -14px rgba(7,151,174,.75)}
.chat-bubble-icon{line-height:1}
.chat-badge{
  position:absolute;top:-7px;right:-7px;min-width:22px;height:22px;padding:0 6px;
  border-radius:999px;background:#C0392B;color:#fff;
  font-family:var(--font-mono);font-size:11px;font-weight:700;
  display:grid;place-items:center;border:1px solid #fff;
}

.chat-panel{
  width:min(94vw,376px);
  /* Anchored to the BOTTOM, so an over-tall panel grows off the TOP of the
     screen and takes its own header and close button with it. On a
     landscape phone the old 76vh plus the bubble, the gap and the sticky
     order bar came to more than the whole viewport. */
  height:min(548px, calc(100dvh - 200px));
  min-height:240px;
  display:flex;flex-direction:column;overflow:hidden;
  border-radius:var(--radius-lg);background:var(--paper);
  border:1px solid var(--line-strong);box-shadow:var(--shadow-lg);
  opacity:0;visibility:hidden;transform:translateY(14px) scale(.985);
  transition:opacity .34s var(--ease),transform .34s var(--ease),visibility .34s;
}
.chat-panel.open{opacity:1;visibility:visible;transform:none}

/* The chat HEAD is a dark band (it re-declares the palette at the top of
   this file); the body below it stays light, so a long conversation reads
   like a conversation and not like a terminal. */
.chat-head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:15px 17px;background:var(--grad-ink);color:#fff;
  position:relative;overflow:hidden;
}
.chat-head::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--grad-line)}
.chat-head-id{display:flex;align-items:center;gap:12px;position:relative;z-index:1;min-width:0}
.chat-head .chat-close{position:relative;z-index:1}
.chat-avatar{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  border-radius:var(--radius);
  background:linear-gradient(180deg,#4EE2F5,#12C4DE);color:var(--on-cyan);
  font-family:var(--font-mono);font-size:12px;font-weight:700;letter-spacing:.06em;
  box-shadow:0 0 20px -6px rgba(18,196,222,.85);
}
.chat-head strong{display:block;font-family:var(--font-display);font-size:15px;font-weight:700;color:#fff}
.chat-status{
  display:flex;align-items:center;gap:8px;
  font-family:var(--font-mono);font-size:10.5px;letter-spacing:.07em;
  color:var(--cyan-light);margin-top:3px;
}
/* The live dot is a pseudo-element on purpose: chat.js writes .textContent
   into this span, which would delete any real child. */
.chat-status::before{
  content:"";width:6px;height:6px;border-radius:50%;flex:none;background:#3EE08F;
  animation:livedot 2.4s var(--ease) infinite;
}
@keyframes livedot{
  0%{box-shadow:0 0 0 0 rgba(62,224,143,.55)}
  70%,100%{box-shadow:0 0 0 7px rgba(62,224,143,0)}
}
.chat-close{
  width:32px;height:32px;border-radius:var(--radius-sm);
  border:1px solid rgba(127,230,245,.3);background:rgba(255,255,255,.05);color:#fff;
  cursor:pointer;font-size:13px;line-height:1;flex:none;transition:background .22s;
}
.chat-close:hover{background:rgba(255,255,255,.16)}

/* Only appears once a returning visitor's thread actually has something
   older than this page load to reveal — see chat.js. Toggled "active"
   (cyan fill) while the earlier conversation is showing, so it reads the
   same way an unmuted/pressed icon does elsewhere on the site. */
.chat-history-btn{
  width:32px;height:32px;border-radius:var(--radius-sm);position:relative;z-index:1;
  border:1px solid rgba(127,230,245,.3);background:rgba(255,255,255,.05);color:#fff;
  cursor:pointer;line-height:1;flex:none;display:grid;place-items:center;transition:background .22s,color .22s;
}
.chat-history-btn svg{display:block}
.chat-history-btn:hover{background:rgba(255,255,255,.16)}
.chat-history-btn.active{background:linear-gradient(180deg,#4EE2F5,#12C4DE);border-color:transparent;color:var(--on-cyan)}

.chat-body{
  flex:1;overflow-y:auto;padding:18px;display:flex;flex-direction:column;gap:12px;
  background:var(--soft);scroll-behavior:smooth;
}
/* The opening greeting is a message from your team, so it is shaped like
   one — at the top, on the left, in a bubble. Centred in an empty panel it
   read as a system notice rather than somebody saying hello. */
.chat-empty{
  align-self:flex-start;max-width:88%;
  font-size:14.5px;line-height:1.65;color:var(--ink-2);
  padding:14px 17px;border-radius:var(--radius-lg);
  background:var(--paper);border:1px solid var(--line);
}
.chat-empty::before{
  content:"InCode Label";display:block;
  font-family:var(--font-mono);font-size:10px;font-weight:700;
  letter-spacing:.18em;text-transform:uppercase;color:var(--cyan-ink);margin-bottom:7px;
}
.chat-msg{max-width:82%;display:flex;flex-direction:column;gap:5px}
.chat-msg-who{
  font-family:var(--font-mono);font-size:10px;font-weight:700;
  letter-spacing:.18em;text-transform:uppercase;color:var(--cyan-ink);
}
.chat-msg-text{
  padding:12px 16px;border-radius:var(--radius-lg);font-size:14.5px;line-height:1.62;
  white-space:pre-wrap;overflow-wrap:break-word;
}
.chat-msg.me{align-self:flex-end;align-items:flex-end}
.chat-msg.me .chat-msg-text{
  background:linear-gradient(180deg,#12C4DE,#0797AE);color:#fff;
  box-shadow:0 8px 22px -14px rgba(7,151,174,.9);
}
.chat-msg.me .chat-msg-who{color:var(--muted)}
.chat-msg.ai .chat-msg-text,.chat-msg.admin .chat-msg-text{
  background:var(--paper);border:1px solid var(--line);color:var(--ink-2);
}
.chat-typing{max-width:82%}
.chat-dots{
  display:inline-flex;gap:5px;padding:14px 17px;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-lg);
}
.chat-dots i{width:6px;height:6px;border-radius:50%;background:var(--cyan);animation:blink 1.3s infinite}
.chat-dots i:nth-child(2){animation-delay:.18s}
.chat-dots i:nth-child(3){animation-delay:.36s}
@keyframes blink{0%,60%,100%{opacity:.25}30%{opacity:1}}

/* One scrolling row. Wrapped onto four stacked rows the starter chips ate a
   third of the panel and squeezed the conversation into a slot too short to
   read a greeting in. */
.chat-suggest{
  display:flex;gap:8px;padding:0 18px 13px;background:var(--soft);
  overflow-x:auto;scrollbar-width:none;
}
.chat-suggest::-webkit-scrollbar{display:none}
.chat-suggest button{
  flex:none;white-space:nowrap;padding:9px 14px;border-radius:999px;
  border:1px solid var(--line-strong);background:var(--paper);color:var(--ink-2);
  font-size:12.5px;font-weight:600;cursor:pointer;transition:.24s var(--ease);
}
.chat-suggest button:hover{border-color:var(--cyan);color:var(--cyan-ink);background:var(--cyan-wash)}

.chat-callrow{
  display:flex;align-items:center;gap:12px;padding:12px 18px;
  border-top:1px solid var(--line);background:var(--cyan-wash);
  font-size:13px;color:var(--cyan-ink);font-weight:600;
}
.chat-callrow a{
  margin-left:auto;display:inline-flex;align-items:center;gap:8px;
  padding:9px 15px;border-radius:var(--radius);
  background:linear-gradient(180deg,#12C4DE,#0797AE);color:#fff;
  font-weight:700;font-size:13px;font-variant-numeric:tabular-nums;
}
.chat-callrow a:hover{filter:brightness(1.06)}

.chat-input-row{display:flex;gap:10px;padding:14px 16px;border-top:1px solid var(--line);background:var(--paper)}
.chat-input-row textarea{
  flex:1;min-width:0;padding:12px 15px;border-radius:var(--radius);
  border:1px solid var(--line-strong);background:var(--paper);
  font-size:14.5px;color:var(--ink);font-family:var(--font-body);
}
.chat-input-row textarea::placeholder{color:var(--muted)}
.chat-input-row textarea:focus{outline:none;border-color:var(--cyan);box-shadow:var(--ring)}
.chat-send{
  width:44px;flex:none;border-radius:var(--radius);border:1px solid var(--cyan);
  background:linear-gradient(180deg,#12C4DE,#0797AE);color:#fff;cursor:pointer;font-size:15px;
  transition:filter .22s var(--ease),transform .22s var(--ease);
}
.chat-send:hover{filter:brightness(1.06);transform:translateY(-1px)}
.chat-local-notice{opacity:.95}

/* ── Responsive ──────────────────────────────────────────────────────── */
@media (max-width:1000px){
  .hero-grid{grid-template-columns:1fr;gap:46px}
  .hero h1{max-width:none}
  .label-demo{transform:none}
  .product-detail-grid{grid-template-columns:1fr}
  .contact-grid{grid-template-columns:1fr}
  .footer-grid{grid-template-columns:1fr 1fr;gap:32px}
}
@media (max-width:760px){
  body{font-size:16px}
  .menu{display:grid;place-items:center}
  .site-header nav{
    position:absolute;left:0;right:0;top:100%;
    flex-direction:column;align-items:stretch;gap:0;
    background:rgba(255,255,255,.97);
    backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px);
    border-bottom:1px solid var(--line-strong);
    padding:8px var(--gut) 18px;
    opacity:0;visibility:hidden;transform:translateY(-8px);
    transition:opacity .25s var(--ease),transform .25s var(--ease),visibility .25s;
  }
  .site-header nav.open{opacity:1;visibility:visible;transform:none}
  .site-header nav a{padding:14px 0;border-bottom:1px solid var(--line);border-radius:0}
  .site-header nav a::after{display:none}
  .footer-grid{grid-template-columns:1fr}
  .cta-band-inner{flex-direction:column;align-items:flex-start}
  .feature-grid{grid-template-columns:1fr}
  .pf-stats{grid-template-columns:1fr 1fr}
  body.has-order-bar .order-bar{display:flex}
  body.has-order-bar{padding-bottom:78px}
  body.has-order-bar .chat-widget{bottom:92px}
  /* Blur is the most expensive thing on a mid-range phone and is doing the
     least work on the smallest screen. Every surface below already has an
     opaque-enough colour under it to carry the panel without it. */
  .feature-card,.category-card,.product-card,.cta-band-inner,
  .pf-stat,.gallery-card,.inq-card,.tab-pill,.eyebrow-pill,
  .btn.ghost,.btn-call,.detail-desc{
    backdrop-filter:none;-webkit-backdrop-filter:none;
  }
}
@media (max-width:420px){
  .hero-actions .btn,.hero-actions .btn-call{width:100%}
}

/* ── Motion preferences ──────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important}
  .js .reveal{opacity:1;transform:none}
  .kin > span{transform:none;opacity:1}
  .spotlight{display:none}
  .label-demo{transform:none}
}


/* ═══════════════════════════════════════════════════════════════════════
   MACHINED METAL
   ═══════════════════════════════════════════════════════════════════════
   The brief was "heavier, more metallic, glassier". Metal on a screen is
   not a texture you paste on; it is a specific behaviour of light, and it
   comes down to three things that are cheap to draw and unmistakable when
   they are all present:

     A BEVEL. Every real machined edge is lit on the side facing the lamp
     and dark on the side away from it. One inset hairline of white along
     the top of a panel and one of black along the bottom is the whole
     illusion — it is what separates "a rectangle with a border" from "a
     piece of something".

     ANISOTROPY. Brushed aluminium scatters light along the direction it
     was brushed, so the highlight is a smeared band rather than a point.
     A very shallow repeating gradient, at a few percent opacity, does it.

     A SPECULAR EDGE. The one bright line where the bevel catches the lamp
     directly. Here it is cyan, because cyan is the light in this room.

   All three are applied through ONE class, `.metal`, plus the existing
   card selectors, so nothing needs new markup and the light-mode surfaces
   are untouched — brushed metal in daylight just reads as dirty.
   ═══════════════════════════════════════════════════════════════════════ */

/* The bevel + brush, on every panel inside a dark band. */
.hero .label-demo,
.section.dark .feature-card, .section.dark .category-card,
.section.dark .product-card, .section.dark .gallery-card,
.section.dark .pf-stat, .section.dark .cta-band-inner,
.order-panel, .contact-note{
  position:relative;
}
.hero .label-demo::after{ /* keeps the corner mark; adds the lit top edge */ }

.order-panel, .contact-note,
.section.dark .cta-band-inner, .section.dark .feature-card,
.section.dark .category-card, .section.dark .pf-stat{
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.16),          /* lit top bevel      */
    inset 0 -1px 0 rgba(0,0,0,.55),               /* shadowed underside */
    var(--shadow-lg);
  background-image:
    /* the brush: a shallow, almost invisible anisotropic grain */
    repeating-linear-gradient(101deg,
      rgba(255,255,255,.030) 0 1px,
      rgba(255,255,255,0)    1px 3px),
    /* the specular band that makes it read as a curved surface */
    linear-gradient(168deg,
      rgba(255,255,255,.10) 0%,
      rgba(255,255,255,.02) 38%,
      rgba(0,0,0,.10)       100%),
    var(--grad-ink);
}
.section.dark .cta-band-inner, .section.dark .feature-card,
.section.dark .category-card, .section.dark .pf-stat{
  background-image:
    repeating-linear-gradient(101deg,
      rgba(255,255,255,.030) 0 1px,
      rgba(255,255,255,0)    1px 3px),
    linear-gradient(168deg, rgba(255,255,255,.085), rgba(255,255,255,.02));
}

/* The hero specimen becomes a milled plate: thicker glass, a brighter top
   edge, and a cyan rim light down one side. */
.hero .label-demo{
  box-shadow:
    inset 0 1px 0 rgba(210,248,255,.24),
    inset 1px 0 0 rgba(120,225,245,.10),
    inset 0 -1px 0 rgba(0,0,0,.6),
    var(--shadow-lg),
    0 0 70px -26px rgba(18,196,222,.5);
  background-image:
    repeating-linear-gradient(101deg, rgba(255,255,255,.035) 0 1px, rgba(255,255,255,0) 1px 3px),
    linear-gradient(165deg, rgba(255,255,255,.13), rgba(255,255,255,.03));
}

/* On WHITE the same idea, inverted and far quieter: polished steel, not
   brushed. A white card gets one hairline of pure white along the top and
   the faintest grey beneath, which is what stops a flat white card on a
   flat white page from disappearing. */
.feature-card, .category-card, .product-card,
.gallery-card, .pf-stat, .cta-band-inner, .inq-card{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(6,23,31,.045),
    var(--shadow);
}

/* The topbar and the header get a machined underside. */
.site-header.is-stuck{
  box-shadow:
    inset 0 -1px 0 rgba(255,255,255,.7),
    0 14px 30px -26px rgba(6,23,31,.55);
}

/* ── The magnifier ────────────────────────────────────────────────────
   A round loupe that follows the pointer over a product image. The circle
   is empty; its BACKGROUND is the same picture scaled up, with the
   background-position moved so the point under the cursor sits in the
   middle. Nothing is downloaded twice and no canvas is involved.

   `will-change:transform` is deliberately NOT set: the lens moves by
   left/top on a rafThrottle, once per frame, and promoting it to its own
   layer costs more than it saves at this size. */
[data-zoom]{cursor:zoom-in}
.zoom-lens{
  position:absolute;left:0;top:0;width:190px;height:190px;
  margin:-95px 0 0 -95px;                 /* centre it on the cursor */
  border-radius:50%;pointer-events:none;z-index:3;
  background-repeat:no-repeat;background-color:transparent;
  border:1px solid rgba(255,255,255,.85);
  box-shadow:
    0 0 0 1px rgba(6,23,31,.28),
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -14px 26px -18px rgba(6,23,31,.6),
    0 22px 46px -18px rgba(6,23,31,.55);
  opacity:0;transform:scale(.9);
  transition:opacity .18s var(--ease),transform .22s var(--ease-out);
}
[data-zoom].zooming .zoom-lens{opacity:1;transform:scale(1)}

/* The "hover to zoom" tag. Present but nearly silent until the pointer is
   over the image — a permanent instruction on a product photo is clutter,
   and an instruction nobody ever sees is useless. */
.zoom-hint{
  position:absolute;right:14px;bottom:14px;z-index:2;
  /* Hidden until initMagnifier() has actually attached a loupe. A product
     with no photograph renders a placeholder glyph, and promising "hover to
     zoom" over a placeholder is a promise the page cannot keep. */
  display:none;align-items:center;gap:7px;
  padding:6px 11px;border-radius:999px;
  background:rgba(8,20,26,.72);color:#DCEFF4;
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;
  text-transform:uppercase;font-weight:700;
  opacity:.55;transition:opacity .22s var(--ease);
}
[data-zoom].zoom-ready .zoom-hint,[data-zoom].zoom-tap .zoom-hint{display:inline-flex}
[data-zoom]:hover .zoom-hint{opacity:1}
[data-zoom].zooming .zoom-hint{opacity:0}
/* On a touch screen there is no hover, so the label says what to do there. */
[data-zoom].zoom-tap .zoom-hint::after{content:" — tap"}

/* ── The full-screen image ────────────────────────────────────────────
   Where a phone goes when the picture is tapped: a dark ground, the image
   as large as it will go, and the browser's own pinch-to-zoom left to do
   the zooming. Deliberately not a custom pinch implementation — the
   browser's is better than any hand-written one and it is the gesture the
   person's thumbs already know. */
.lightbox{
  position:fixed;inset:0;z-index:120;display:none;
  align-items:center;justify-content:center;padding:24px;
  background:rgba(3,8,11,.94);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  opacity:0;transition:opacity .22s var(--ease);
}
.lightbox.open{display:flex;opacity:1}
.lightbox img{
  max-width:100%;max-height:100%;object-fit:contain;
  background:transparent;border-radius:var(--radius-lg);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.9), 0 0 90px -30px rgba(18,196,222,.45);
}
.lightbox-close{
  position:absolute;top:20px;right:20px;width:44px;height:44px;
  border-radius:50%;cursor:pointer;font-size:16px;line-height:1;
  color:#EAF6F9;background:rgba(255,255,255,.08);
  border:1px solid rgba(127,230,245,.32);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  transition:background .2s var(--ease),transform .2s var(--ease);
}
.lightbox-close:hover{background:rgba(18,196,222,.22);transform:scale(1.06)}
body.lightbox-open{overflow:hidden}

/* ── Chat starters that are all reachable ─────────────────────────────
   They used to sit in one row that scrolled sideways with the scrollbar
   hidden, so in a 376px panel the third chip was cut in half and the
   fourth was off-screen with nothing to hint that sideways was a direction
   you could go. They wrap now. The chips were shortened to two or three
   words each (see chat.js) so all four fit on two rows without eating the
   conversation, which is what made wrapping unworkable the first time. */
.chat-suggest{
  flex-wrap:wrap;overflow-x:visible;
  max-height:none;
}
.chat-suggest button{white-space:nowrap}


/* ═══════════════════════════════════════════════════════════════════════
   APERTURE — the instrument layer
   ═══════════════════════════════════════════════════════════════════════
   The brief: one theme in which light and dark are combined, not two
   themes with a switch. Heavier, more metallic, glassier, cinematic, and
   not recognisable as any other website.

   The idea this layer commits to is that the page is the DISPLAY OF A
   PRECISION INSTRUMENT — the thing a label house actually is. That gives
   a reason for every decision below, and it is where the light/dark answer
   comes from:

     An instrument is never all one tone. It has a machined dark chassis and
     a lit readout, and they sit INSIDE each other. So here, light and dark
     do not alternate down the page in bands — they interlock inside every
     single component. A white section carries a dark milled chip. A light
     product plate sits above a dark data rail. A light chat body hangs
     under a dark instrument head. At every scale, both.

   Four devices carry it, and nothing else is added:

     1. THE FRAME. A hairline inset from the viewport with corner brackets,
        always there, never scrolling. It turns the browser window into a
        housing and every page into something mounted inside it.
     2. THE CHIP. Every section eyebrow becomes a small dark machined plate
        with a cyan monospace legend. This is the dark element that appears
        in even the whitest section.
     3. THE RAIL. Cards get a dark data rail carrying the number and the
        action, under a lit plate carrying the product.
     4. THE BEVEL. Lit top edge, shadowed underside, shallow brushed grain.
        Metal is not a texture, it is a behaviour of light.

   Everything here is layered ON TOP of the palette above, so nothing that
   already works is rewritten and the dark bands keep their own behaviour.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. THE FRAME ─────────────────────────────────────────────────────
   Fixed, ignores the pointer, and drawn in four corner brackets rather
   than a full box — a closed rectangle around a web page reads as a
   border, four brackets read as an instrument's housing. It is drawn with
   gradients on one element so it costs one paint and no markup.

   It hides below 900px: on a phone the viewport IS the housing, and 14px
   of chrome on each side is 8% of the screen spent on decoration. */
@media (min-width:900px){
  body::before{
    content:"";position:fixed;inset:13px;z-index:95;pointer-events:none;
    border:1px solid rgba(7,151,174,.16);
    /* the four brackets, brighter than the hairline they interrupt */
    background:
      linear-gradient(var(--cyan),var(--cyan)) left  top    /1px 26px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) left  top    /26px 1px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) right top    /1px 26px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) right top    /26px 1px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) left  bottom /1px 26px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) left  bottom /26px 1px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) right bottom /1px 26px no-repeat,
      linear-gradient(var(--cyan),var(--cyan)) right bottom /26px 1px no-repeat;
    opacity:.55;
  }
}
/* The chat clears the frame. The HEADER deliberately does not.

   Offsetting a sticky header to sit inside the frame leaves a 13px slot
   above it that the page scrolls through — a sliver of moving text over
   the top of the screen, which looks like a rendering fault rather than a
   design. The frame is drawn at a higher layer instead, so its top
   hairline simply crosses the header. A housing that the instrument's own
   fascia passes behind is what a real one looks like anyway. */
@media (min-width:900px){
  .chat-widget{right:36px;bottom:36px}
}

/* An eyebrow is a small plate, never a full-width bar. Inside the card
   rails and the contact column it sits in a stretching flex column, which
   was pulling it to the whole width of the card. */
.eyebrow,.eyebrow-pill{align-self:flex-start}

/* ── 2. THE CHIP ──────────────────────────────────────────────────────
   The single most repeated element on the site, and now the place where
   dark meets light in every section. A milled dark plate, cyan monospace
   legend, lit top edge, seated with a shadow so it reads as a physical
   part fixed to the page rather than coloured text.

   Inside a dark band it inverts to a lit plate on the dark ground, so the
   same component keeps doing the same job — being the other tone. */
.eyebrow{
  padding:6px 13px 6px 11px;border-radius:6px;
  background:linear-gradient(178deg,#12242E,#08161D);
  color:var(--cyan-bright);
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.20),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 6px 16px -10px rgba(6,23,31,.85);
  letter-spacing:.2em;
}
.eyebrow::before{
  width:12px;background:var(--cyan-bright);
  box-shadow:0 0 9px rgba(78,226,245,.9);
}
/* On a dark ground the chip becomes the lit one. */
.hero .eyebrow,.section.dark .eyebrow,footer .eyebrow,
.hero .eyebrow-pill{
  background:linear-gradient(178deg,rgba(255,255,255,.13),rgba(255,255,255,.045));
  box-shadow:
    inset 0 1px 0 rgba(210,248,255,.28),
    inset 0 -1px 0 rgba(0,0,0,.45),
    0 0 26px -12px rgba(18,196,222,.8);
}
.eyebrow-pill{
  background:linear-gradient(178deg,#12242E,#08161D);
  color:var(--cyan-bright);border-color:rgba(127,230,245,.2);
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.20),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 8px 20px -12px rgba(6,23,31,.9);
}
.eyebrow-pill::before{background:var(--cyan-bright);box-shadow:0 0 9px rgba(78,226,245,.9)}

/* ── 3. THE RAIL ──────────────────────────────────────────────────────
   A product card is now two materials stacked: a lit plate holding the
   photograph, and a dark machined rail holding the number and the button.
   That is what a scale, a caliper or a label printer looks like, and it
   does the job a card has to do — the eye goes to the picture, then drops
   to the figure, because the figure is on a different material. */
.product-card .product-body{
  background:linear-gradient(178deg,#0E2029,#081820);
  color:var(--ink-2);
  box-shadow:inset 0 1px 0 rgba(190,240,250,.14);
  background-image:
    repeating-linear-gradient(101deg, rgba(255,255,255,.028) 0 1px, rgba(255,255,255,0) 1px 3px),
    linear-gradient(178deg,#0E2029,#081820);
}
.product-card .product-body h3 a{color:#fff}
.product-card .product-body h3 a:hover{color:var(--cyan-bright)}
.product-card .price{color:#fff}
.product-card .price-note,.product-card .muted{color:#7EA0AC}
.product-card .price-unit{background:rgba(18,196,222,.14);border-color:rgba(18,196,222,.4);color:var(--cyan-bright)}
.product-card .price-ask{color:var(--cyan-bright)}
.product-card .spec-chips span{
  background:rgba(255,255,255,.05);border-color:rgba(127,230,245,.15);color:#9FC0CB;
}
.product-card .card-call{
  background:rgba(18,196,222,.12);border-color:rgba(18,196,222,.45);color:var(--cyan-bright);
}
.product-card .card-call:hover{
  background:linear-gradient(180deg,#4EE2F5,#12C4DE);color:#02171C;
  border-color:rgba(157,239,251,.6);box-shadow:0 10px 30px -12px rgba(18,196,222,.85);
}
/* Same dark-plate glass treatment as the Call button above, in the
   WhatsApp green, so the two sit as one matched pair on the card instead
   of one looking like a premium pill and the other a flat tag. */
.product-card .card-whatsapp{
  background:rgba(79,227,155,.12);border-color:rgba(79,227,155,.45);color:#4FE39B;
}
.product-card .card-whatsapp:hover{
  background:linear-gradient(180deg,#6BEEB0,#17A85B);color:#02180F;
  border-color:rgba(178,247,212,.6);box-shadow:0 10px 30px -12px rgba(23,168,91,.85);
}
.product-card{border-color:rgba(6,23,31,.14)}
.product-card:hover{border-color:var(--cyan)}

/* The gallery caption is the same rail, shorter. */
.gallery-card .gallery-cap{
  background:linear-gradient(178deg,#0E2029,#081820);
  color:#A9C6D1;box-shadow:inset 0 1px 0 rgba(190,240,250,.14);
}
.gallery-card .pf-tag{
  background:rgba(18,196,222,.13);border-color:rgba(18,196,222,.42);color:var(--cyan-bright);
}

/* A feature card gets its index milled into the corner instead. */
.feature-card{padding-top:34px}
.feature-card::after{
  content:"";position:absolute;right:0;top:0;width:44px;height:26px;
  background:linear-gradient(178deg,#12242E,#08161D);
  border-bottom-left-radius:10px;
  box-shadow:inset 0 1px 0 rgba(190,240,250,.18);
  pointer-events:none;
}

/* ── 4. THE HEADER, as a machined rail ────────────────────────────────
   Dark, so the page opens with the chassis and the content sits lit
   beneath it. Smoked, so the hero's light moves behind it. */
.site-header{
  /* Opaque enough that the page does not smear through it.

     At .72 this was properly frosted over the dark hero and a muddy grey
     smudge over the white pages, with headings legibly ghosting through
     the fascia as they scrolled under it. Dark glass over a light ground
     needs far more body than dark glass over a dark one, and the header
     has to work over both. The blur and the saturation stay — they are
     what keep it glass rather than a painted bar. */
  background:rgba(6,18,24,.94);
  backdrop-filter:blur(24px) saturate(170%);-webkit-backdrop-filter:blur(24px) saturate(170%);
  border-bottom:1px solid rgba(127,230,245,.14);
  box-shadow:inset 0 1px 0 rgba(190,240,250,.13), inset 0 -1px 0 rgba(0,0,0,.5);
}
.site-header.is-stuck{
  background:rgba(4,13,18,.97);
  border-bottom-color:rgba(127,230,245,.24);
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.16),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 22px 44px -34px rgba(0,0,0,.9);
}
.site-header .brand{color:#fff}
.site-header .brand .accent{color:var(--cyan-bright);text-shadow:0 0 22px rgba(18,196,222,.65)}
.site-header nav a{color:#A9C6D1}
.site-header nav a::after{background:var(--cyan-bright);box-shadow:0 0 10px rgba(78,226,245,.9)}
.site-header nav a:hover{color:#fff;background:rgba(127,230,245,.08)}
.menu{
  background:rgba(255,255,255,.06);border-color:rgba(127,230,245,.24);color:#EAF6F9;
}
@media (max-width:760px){
  .site-header nav{
    background:rgba(6,18,24,.97);border-bottom-color:rgba(127,230,245,.22);
  }
  .site-header nav a{border-bottom-color:rgba(127,230,245,.12)}
}

/* ── 5. THE PLATE, lit from within ────────────────────────────────────
   The product image plate gains an inner rim light along its top edge, so
   it reads as a lit surface set into the card rather than a pale
   rectangle painted on it. */
.product-image::before,
.product-detail-image::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95), inset 0 0 0 1px rgba(6,23,31,.06);
}
.product-detail-image::before{border-radius:inherit}

/* ── 6. TYPE, tightened ───────────────────────────────────────────────
   The one change that reads as "expensive" before any colour does:
   headlines set tighter and heavier, micro-labels opened right out. */
h1{letter-spacing:-.038em}
h2{letter-spacing:-.032em}
.hero h1{letter-spacing:-.042em}
.price,.order-price,.pf-stat strong,.ob-price{letter-spacing:-.04em}

/* ── 7. THE CHAT, as an instrument ────────────────────────────────────
   Dark machined head, lit conversation beneath it — the same two materials
   as everything else, at the smallest scale on the page. */
.chat-bubble{
  border-radius:16px;
  background:linear-gradient(178deg,#12242E,#07151C);
  border:1px solid rgba(127,230,245,.3);
  color:var(--cyan-bright);
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.22),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 14px 34px -16px rgba(6,23,31,.9),
    0 0 30px -14px rgba(18,196,222,.7);
}
.chat-bubble:hover{
  color:#fff;border-color:var(--cyan-bright);
  box-shadow:
    inset 0 1px 0 rgba(210,248,255,.3),
    0 18px 44px -16px rgba(6,23,31,.9),
    0 0 46px -12px rgba(18,196,222,.95);
}
.chat-bubble-icon{display:grid;place-items:center}
.chat-bubble-icon svg{display:block}
.chat-badge{box-shadow:0 0 0 2px rgba(8,22,29,.9), 0 6px 14px -6px rgba(0,0,0,.8)}
.chat-whatsapp-fab{
  border-radius:var(--radius-lg);
  background:linear-gradient(178deg,#1FAE55,#0F7A3E);
  border:1px solid rgba(79,227,155,.4);
  box-shadow:
    inset 0 1px 0 rgba(190,250,220,.22),
    inset 0 -1px 0 rgba(0,0,0,.5),
    0 12px 28px -14px rgba(6,23,31,.9);
}
.chat-whatsapp-fab:hover{
  border-color:#4FE39B;
  box-shadow:
    inset 0 1px 0 rgba(210,255,235,.3),
    0 16px 36px -14px rgba(6,23,31,.9),
    0 0 30px -12px rgba(37,211,102,.8);
}
.chat-panel{
  border-radius:16px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    var(--shadow-lg),
    0 0 70px -34px rgba(18,196,222,.5);
}
.chat-head{
  background-image:
    repeating-linear-gradient(101deg, rgba(255,255,255,.03) 0 1px, rgba(255,255,255,0) 1px 3px),
    var(--grad-ink);
  box-shadow:inset 0 1px 0 rgba(190,240,250,.18), inset 0 -1px 0 rgba(0,0,0,.5);
}
.chat-send,.chat-close{display:grid;place-items:center}
.chat-send svg,.chat-close svg{display:block}

/* ── 8. THE SCROLL FILAMENT ───────────────────────────────────────────
   Thicker, lit, and seated in a dark channel so it reads as a gauge
   rather than a coloured line. */
.scroll-rail{height:3px;background:rgba(8,22,29,.5)}
.scroll-rail i{
  background:linear-gradient(90deg,var(--cyan-deep),#4EE2F5);
  box-shadow:0 0 14px rgba(18,196,222,.9);
}

/* ── 9. BUTTONS, machined ─────────────────────────────────────────────
   The primary is a milled dark key with a lit rim; on a dark band the
   palette already flips it to a cyan lamp. */
.btn.primary{
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.22),
    inset 0 -1px 0 rgba(0,0,0,.55),
    var(--btn-shadow);
}
.btn.ghost,.btn-call{
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1px 0 rgba(6,23,31,.05);
}
.hero .btn.ghost,.hero .btn-call,
.section.dark .btn.ghost,.section.dark .btn-call{
  box-shadow:inset 0 1px 0 rgba(190,240,250,.18), inset 0 -1px 0 rgba(0,0,0,.4);
}

/* ── 10. THE FOOTER PLINTH ────────────────────────────────────────────
   The page ends on the chassis, with one lit hairline where it meets the
   content above it. */
footer::before{height:1px;opacity:1;box-shadow:0 0 18px rgba(18,196,222,.55)}

@media (prefers-reduced-motion: reduce){
  .chat-bubble,.btn,.btn-call,.chat-whatsapp-fab{transition:none !important}
}

/* ═══════════════════════════════════════════════════════════════════════
   CINEMATIC GLASS — v2 UPGRADE LAYER
   ---------------------------------------------------------------------------
   The owner's brief: nothing about the previous look should survive as-is.
   Heavier, more high-end, more "next level" — full cinematic glassmorphism
   everywhere, on the white pages as much as the dark ones, white+cyan the
   whole way through, light and dark united in one epic material.

   This layer does not rewrite the file above — every existing class and
   every script-generated element keeps working exactly as before. It turns
   the same tokens up: real frosted glass on white pages (previously off on
   purpose), a permanent ambient cyan atmosphere behind every page, stronger
   glow on every card, and a purpose-built cinematic treatment for the
   product page — the page a buyer actually decides on. Because it is
   appended last, it wins the cascade without needing !important anywhere.
   ═══════════════════════════════════════════════════════════════════════ */

:root{
  /* Frosted glass switched ON for the light pages too — the single change
     that turns every .feature-card/.category-card/.product-card/.gallery-
     card/.cta-band-inner/.tab-pill/.btn.ghost/.btn-call into real glass,
     because they already read this token. */
  --glass:blur(24px) saturate(190%);

  /* Cards become translucent panes instead of flat white paper, so the
     ambient atmosphere below shows through them like light through a
     showroom window. */
  --card-bg:linear-gradient(166deg,rgba(255,255,255,.86),rgba(255,255,255,.58));
  --card-bg-2:rgba(255,255,255,.62);
  --card-border:rgba(18,196,222,.22);
  --field-bg:rgba(255,255,255,.72);
  --chip-bg:linear-gradient(166deg,rgba(255,255,255,.75),rgba(231,243,247,.45));

  /* Glow switched on everywhere, at a level judged for a WHITE ground —
     enough to feel lit, never enough to muddy the paper. */
  --glow:0 0 1px rgba(18,196,222,.05),0 30px 70px -26px rgba(7,151,174,.42);
  --glow-ring:0 0 0 1px rgba(18,196,222,.22);
  --text-glow:0 0 18px rgba(7,151,174,.22);

  --shadow-lg:0 2px 5px rgba(6,23,31,.05), 0 46px 90px -36px rgba(6,23,31,.4);
  --radius-lg:16px;
  --radius-xl:24px;
}

/* ── The atmosphere ─────────────────────────────────────────────────────
   Fixed behind the entire document — three slow cyan blooms and a hairline
   of film grain. This is what the new frosted glass actually blurs; a
   glass pane over flat white paper is just a soft-edged rectangle, a glass
   pane over light is a window. Sits at the very back of the stack, drawn
   once, never repainted on scroll. */
body{position:relative;background:#FBFEFF}
body::before{
  content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;
  background:
    radial-gradient(1100px 620px at 88% -12%, rgba(18,196,222,.16), transparent 60%),
    radial-gradient(820px 560px at -8% 22%,  rgba(7,151,174,.11),  transparent 58%),
    radial-gradient(900px 620px at 46% 112%, rgba(4,96,116,.13),   transparent 60%),
    linear-gradient(180deg,#FFFFFF 0%,#F8FCFD 100%);
  animation:atmoDrift 26s var(--ease-soft) infinite alternate;
}
body::after{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--grain-soft);background-size:160px 160px;
  opacity:.35;mix-blend-mode:multiply;
}
@keyframes atmoDrift{
  from{background-position:0 0,0 0,0 0,0 0}
  to  {background-position:2% -2%,-2% 2%,-1% 1%,0 0}
}
@media (min-width:900px){ body::before{z-index:-2} }
@media (prefers-reduced-motion: reduce){ body::before{animation:none} }

/* ── Every card is now a true glass pane ─────────────────────────────── */
.feature-card,.category-card,.product-card,.cta-band-inner,.pf-stat,
.gallery-card,.inq-card,.tab-pill,.eyebrow-pill,.skeleton{
  box-shadow:0 1px 0 rgba(255,255,255,.7) inset, 0 26px 54px -34px rgba(6,23,31,.28);
}
.feature-card::after,.category-card::after,.product-card::after,.gallery-card::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:1;
  background:linear-gradient(155deg,rgba(255,255,255,.5) 0%,transparent 26%);
  mix-blend-mode:overlay;
}
.category-card::after{content:"→";background:none;mix-blend-mode:normal} /* restore the arrow glyph */
.feature-card:hover,.category-card:hover,.product-card:hover,.gallery-card:hover{
  box-shadow:var(--shadow-lg),var(--glow), 0 1px 0 rgba(255,255,255,.8) inset;
}

/* ── Product listing plate — a touch more premium ─────────────────────── */
.product-image::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:linear-gradient(155deg,rgba(255,255,255,.55),transparent 40%);
  mix-blend-mode:overlay;
}
.price{text-shadow:0 0 24px rgba(7,151,174,.12)}

/* ── Buttons — deeper glass, sharper light sweep ───────────────────────── */
.btn.ghost,.btn-call,.btn-whatsapp{box-shadow:var(--glow-ring),inset 0 1px 0 rgba(255,255,255,.85),0 18px 40px -26px rgba(6,23,31,.35)}
.btn.primary{box-shadow:var(--btn-shadow),0 0 44px -18px rgba(18,196,222,.4)}

/* ═══════════════════════════════════════════════════════════════════════
   THE PRODUCT PAGE — full cinematic treatment
   The page a customer actually converts on. It gets its own atmosphere,
   a genuinely epic glass specimen frame, a description card that reads
   like a spec sheet under glass, and an order panel that behaves like the
   hero: it breathes.
   ═══════════════════════════════════════════════════════════════════════ */

.section[data-page="product-detail"]{
  position:relative;isolation:isolate;overflow:hidden;
  padding-top:clamp(52px,6vw,88px);
}
.section[data-page="product-detail"]::before{
  /* replaces the printed registration ticks on this page only, with a lit
     floor-grid that fades toward the reader — the hero's language, brought
     to a white page. */
  background-image:
    linear-gradient(rgba(7,151,174,.07) 1px,transparent 1px),
    linear-gradient(90deg,rgba(7,151,174,.07) 1px,transparent 1px);
  background-size:64px 64px;opacity:1;
  mask-image:radial-gradient(120% 70% at 50% 0%,#000 0%,transparent 78%);
  -webkit-mask-image:radial-gradient(120% 70% at 50% 0%,#000 0%,transparent 78%);
}
.section[data-page="product-detail"] .container{position:relative;z-index:1}
.section[data-page="product-detail"]::after{
  content:"";position:absolute;z-index:0;pointer-events:none;
  right:-14%;top:-22%;width:64%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(18,196,222,.20),transparent 66%);
  filter:blur(70px);
  animation:breathe 16s var(--ease-soft) infinite alternate;
}

.breadcrumb{
  padding:8px 16px;border-radius:999px;display:inline-flex;width:fit-content;
  background:var(--card-bg-2);border:1px solid var(--card-border);
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
}

/* The specimen frame — glass, corner-lit, floating. */
.product-detail-image{
  background:rgba(255,255,255,.06);
  backdrop-filter:blur(26px) saturate(190%);-webkit-backdrop-filter:blur(26px) saturate(190%);
  border:1px solid rgba(18,196,222,.3);border-radius:var(--radius-xl);
  box-shadow:
    0 1px 0 rgba(255,255,255,.8) inset,
    0 40px 90px -34px rgba(6,23,31,.34),
    0 0 100px -34px rgba(18,196,222,.5);
  transition:transform .7s var(--ease-out),box-shadow .5s var(--ease);
}
.product-detail-image::before,.product-detail-image::after{
  width:22px;height:22px;border-color:var(--cyan-bright);
  box-shadow:0 0 16px rgba(18,196,222,.75);opacity:1;
}
.product-detail-image:hover{
  transform:translateY(-6px);
  box-shadow:
    0 1px 0 rgba(255,255,255,.85) inset,
    0 54px 110px -32px rgba(6,23,31,.4),
    0 0 130px -30px rgba(18,196,222,.65);
}
.zoom-hint{
  position:absolute;left:50%;bottom:14px;transform:translateX(-50%);
  display:inline-flex;align-items:center;gap:7px;padding:7px 14px;
  border-radius:999px;background:rgba(6,23,31,.82);color:var(--cyan-light);
  font-family:var(--font-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  opacity:0;transition:opacity .3s var(--ease);pointer-events:none;
  box-shadow:0 10px 26px -12px rgba(6,23,31,.6);
}
.product-detail-image:hover .zoom-hint{opacity:1}

.product-detail h1{
  background:linear-gradient(180deg,var(--ink),var(--ink-2));
  -webkit-background-clip:text;background-clip:text;color:var(--ink);
}
.product-detail .spec-chips span{
  background:var(--chip-bg);border-color:rgba(18,196,222,.32);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  font-weight:700;letter-spacing:.16em;color:var(--cyan-ink);
  box-shadow:0 8px 20px -14px rgba(6,23,31,.25);
}

/* The description — a glass spec sheet, not a flat tinted box. */
.detail-desc{
  background:linear-gradient(165deg,rgba(255,255,255,.78),rgba(231,243,247,.42));
  backdrop-filter:blur(22px) saturate(170%);-webkit-backdrop-filter:blur(22px) saturate(170%);
  border:1px solid rgba(18,196,222,.26);border-left:3px solid var(--cyan-bright);
  border-radius:var(--radius-xl);
  box-shadow:0 1px 0 rgba(255,255,255,.8) inset, 0 30px 60px -34px rgba(6,23,31,.3);
  position:relative;overflow:hidden;
}
.detail-desc::before{
  content:"";position:absolute;left:-30%;top:-140%;width:60%;height:260%;pointer-events:none;
  background:radial-gradient(circle,rgba(18,196,222,.16),transparent 65%);filter:blur(30px);
}

/* The order panel now breathes like the hero specimen card — the same
   material, the same behaviour, on the page that matters most. */
.order-panel{
  border-radius:var(--radius-xl);
  box-shadow:
    0 1px 0 rgba(255,255,255,.06) inset,
    var(--shadow-lg),
    0 0 90px -30px rgba(18,196,222,.55);
  animation:panelBreathe 7s var(--ease-soft) infinite alternate;
}
@keyframes panelBreathe{
  from{box-shadow:0 1px 0 rgba(255,255,255,.06) inset,var(--shadow-lg),0 0 80px -32px rgba(18,196,222,.48)}
  to  {box-shadow:0 1px 0 rgba(255,255,255,.08) inset,var(--shadow-lg),0 0 120px -26px rgba(18,196,222,.68)}
}
.order-panel::before{height:2px;box-shadow:0 0 16px rgba(18,196,222,.7)}
.order-price{text-shadow:0 0 60px rgba(18,196,222,.55),0 0 16px rgba(78,226,245,.5)}
.order-actions .btn,.order-actions .btn-call,.order-actions .btn-whatsapp{backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%)}

.gallery-grid .gallery-card{backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass)}

@media (max-width:760px){
  .section[data-page="product-detail"]::after{display:none}
}

/* ── Print — the atmosphere layer must never reach paper ───────────────── */
@media print{
  body::before,body::after{display:none !important}
  .section[data-page="product-detail"]::after{display:none !important}
}

/* ── Print ───────────────────────────────────────────────────────────
   Paper is white and toner is expensive, so the dark bands are inverted
   back for print. A dark band sent to a printer is a solid black page. */
@media print{
  .site-header,.chat-widget,.order-bar,footer,.hero-bg,.grid-lines,
  .scroll-rail,.spotlight,.hero-glow{display:none !important}
  body::before{display:none !important}
  html,body{background:#fff !important}
  body{font-size:12pt;color:#000}
  .hero,.section.dark{background:#fff !important;background-image:none !important}
  h1,h2,h3,h4,.price,.order-price,.pf-stat strong,.brand,.hero h1{color:#000 !important;text-shadow:none !important}
  .lead,.muted,.tiny,.small,p{color:#222 !important}
  .accent,.hero h1 .accent{color:#046074 !important;text-shadow:none !important}
  .hero h1 .accent::before{display:none !important}
  .section{padding:14pt 0;border-top:1px solid #ccc}
  .section::before,.section::after{display:none !important}
  .feature-card,.category-card,.product-card,.cta-band-inner,.pf-stat,
  .gallery-card,.inq-card,.order-panel,.contact-note,.detail-desc,
  .tab-pill,.btn,.eyebrow-pill,.pf-stats,.label-demo{
    background:#fff !important;background-image:none !important;
    border-color:#999 !important;color:#000 !important;
    box-shadow:none !important;backdrop-filter:none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   MONUMENTAL — v3 EPIC CINEMATIC UPGRADE
   ---------------------------------------------------------------------------
   Brief: nothing about the current look survives as-is. Heavier, more
   high-end, more "next level" than the v2 glass pass — full cinematic
   glassmorphism pushed to a monumental, mesmerizing register, white+cyan
   the entire way through, one unified theme where the light stretches and
   the dark stretches are two moods of the same material, not two themes.

   Appended last, so it wins the cascade with zero !important. Nothing
   below removes a class or a script hook — every element the pages and
   app.js depend on keeps its name and its job. This layer only makes the
   same names heavier, deeper, and lit.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. Monumental scale & type ────────────────────────────────────────── */
:root{
  --radius-lg:18px;
  --radius-xl:28px;
  --ease-epic:cubic-bezier(.16,1,.3,1);
}
h1{font-size:clamp(42px,6.4vw,92px);letter-spacing:-.035em}
.hero h1{letter-spacing:-.045em;line-height:1.02}
.page-hero h1{font-size:clamp(36px,5vw,66px)}
h2{font-size:clamp(30px,4vw,54px)}
.lead{font-size:clamp(17px,1.5vw,20.5px)}

/* Custom, cinematic scrollbar — thin cyan filament in a dark channel. */
html{scrollbar-width:thin;scrollbar-color:#12C4DE rgba(6,23,31,.15)}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:rgba(6,23,31,.06)}
::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,#4EE2F5,#0797AE);border-radius:99px;
  border:2px solid rgba(255,255,255,.6);
}

/* ── 2. The atmosphere, turned into a full cinematic environment ────────
   Bigger blooms, a third depth layer, a slow light sweep that crosses the
   whole document, and a permanent soft vignette that pulls the eye to the
   centre column the way a lens does. */
body{background:#FBFEFF}
body::before{
  background:
    radial-gradient(1300px 760px at 90% -16%, rgba(18,196,222,.19), transparent 60%),
    radial-gradient(980px 680px at -10% 18%,  rgba(7,151,174,.13),  transparent 58%),
    radial-gradient(1000px 700px at 50% 118%, rgba(4,96,116,.15),   transparent 60%),
    radial-gradient(1600px 900px at 50% 50%,  transparent 55%, rgba(4,26,34,.05) 100%),
    linear-gradient(180deg,#FFFFFF 0%,#F7FCFD 100%);
  animation:atmoDrift 30s var(--ease-epic) infinite alternate;
}
@keyframes lightSweep{
  0%{transform:translateX(-120%) skewX(-12deg)}
  100%{transform:translateX(220%) skewX(-12deg)}
}
.hero::after{
  content:"";position:absolute;inset:-10% -40%;z-index:-1;pointer-events:none;
  width:36%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.05),transparent);
  animation:lightSweep 9s linear infinite;
}
@media (prefers-reduced-motion: reduce){ .hero::after{animation:none;display:none} }

/* ── 3. Header — the machined rail, final finish ─────────────────────────
   Earlier drafts of this pass reused the pale-glass fascia from the very
   first version of the header and it read as washed-out white-on-white —
   the brand and nav labels are set in white / pale cyan-grey specifically
   for the dark rail below, so the rail has to stay dark and near-opaque
   on every page, not just the home hero. Fixed here: same premium finish
   (deeper blur, glowing seam, heavier shadow) but back on its dark ground,
   so "InCodeLabel" and the nav links are crisp on every page. */
.site-header{
  background:rgba(5,15,20,.88);
  backdrop-filter:blur(30px) saturate(200%);
  -webkit-backdrop-filter:blur(30px) saturate(200%);
  border-bottom:1px solid rgba(127,230,245,.16);
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.14),
    inset 0 -1px 0 rgba(0,0,0,.5),
    0 24px 60px -44px rgba(0,0,0,.6);
}
.site-header::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:linear-gradient(90deg,transparent,rgba(78,226,245,.75),transparent);
  opacity:.9;
}
.site-header.is-stuck{
  background:rgba(4,12,17,.96);
  box-shadow:
    inset 0 1px 0 rgba(190,240,250,.16),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 30px 70px -40px rgba(0,0,0,.75);
}
.site-header .nav{height:82px}
.site-header .brand{font-size:25px;letter-spacing:-.035em;color:#fff}
.site-header .brand .accent{color:var(--cyan-bright);text-shadow:0 0 26px rgba(18,196,222,.7)}
.site-header nav a{font-size:14px;letter-spacing:.01em;color:#A9C6D1;font-weight:600}
.site-header nav a:hover{color:#fff;background:rgba(127,230,245,.08)}
.site-header nav a::after{
  height:2px;border-radius:2px;
  background:var(--cyan-bright);
  box-shadow:0 0 10px rgba(78,226,245,.9);
}
.site-header nav a.is-active{color:#fff}
.site-header nav a.is-active::after{transform:scaleX(1)}
.menu{
  background:rgba(255,255,255,.06);border-color:rgba(127,230,245,.24);color:#EAF6F9;
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  box-shadow:inset 0 1px 0 rgba(190,240,250,.14), 0 10px 26px -18px rgba(0,0,0,.4);
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease),background .25s var(--ease);
}
.menu:hover{border-color:var(--cyan-bright);background:rgba(127,230,245,.1)}

/* ── 4. Hero — the monumental stage ──────────────────────────────────────
   A cinema-scale opener: deeper floor, brighter orbs with slow parallax
   drift, a heavier eyebrow chip, kinetic accent word with a moving glint,
   and a hero card that reads as a lit specimen suspended in the room. */
.hero{
  padding:clamp(92px,10vw,168px) 0 clamp(88px,9vw,150px);
}
.orb-cyan{
  box-shadow:0 0 240px 100px rgba(18,196,222,.30);
  animation-duration:16s;
}
.orb-cyan-soft{
  box-shadow:0 0 300px 130px rgba(4,96,116,.22);
}
.eyebrow-pill{
  padding:9px 18px;font-size:11.5px;letter-spacing:.2em;
  border-radius:999px;
  background:linear-gradient(160deg,rgba(255,255,255,.14),rgba(255,255,255,.03));
  border:1px solid rgba(127,230,245,.32);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  box-shadow:0 1px 0 rgba(255,255,255,.12) inset, 0 14px 30px -20px rgba(0,0,0,.6);
}
.hero h1 .accent{
  text-shadow:0 0 36px rgba(18,196,222,.55),0 0 90px rgba(18,196,222,.25);
}
.hero .lead{font-size:clamp(17.5px,1.5vw,21px);max-width:52ch}

.hero-card{filter:drop-shadow(0 40px 90px rgba(0,0,0,.55))}
.hero-glow{
  box-shadow:0 0 220px 80px rgba(18,196,222,.35);
}
.label-demo{
  border-radius:var(--radius-xl);
  box-shadow:
    0 1px 0 rgba(255,255,255,.14) inset,
    0 50px 100px -34px rgba(0,0,0,.75),
    0 0 130px -30px rgba(18,196,222,.6);
  backdrop-filter:blur(30px) saturate(200%);-webkit-backdrop-filter:blur(30px) saturate(200%);
}
.label-demo::before,.label-demo::after{
  width:26px;height:26px;border-color:rgba(157,239,251,.9);
  box-shadow:0 0 18px rgba(18,196,222,.8);
}
.barcode-real{box-shadow:0 0 46px -6px rgba(18,196,222,.6), 0 14px 34px -14px rgba(0,0,0,.95)}

.trust{gap:22px}
.trust span{
  display:inline-flex;align-items:center;gap:7px;
  padding:6px 12px;border-radius:999px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}

/* ── 5. Buttons — liquid glass with a moving sheen ───────────────────────
   The primary key becomes a lit ingot; the ghost/call pill a true glass
   capsule. Same classes, same click targets, dramatically heavier finish. */
.btn,.btn-call{
  border-radius:999px;padding:15px 30px;font-size:14.5px;letter-spacing:.02em;
  transition:transform .45s var(--ease-epic),box-shadow .45s var(--ease-epic),
             border-color .3s var(--ease),background .3s var(--ease);
}
.btn.primary{
  background:var(--btn-bg);position:relative;overflow:hidden;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.3),
    inset 0 -2px 6px rgba(0,0,0,.35),
    var(--btn-shadow),0 0 60px -20px rgba(18,196,222,.5);
}
.btn.primary:hover{transform:translateY(-3px) scale(1.015)}
.btn.ghost,.btn-call{
  backdrop-filter:blur(22px) saturate(190%);-webkit-backdrop-filter:blur(22px) saturate(190%);
  border-width:1.5px;
}
.btn.ghost:hover,.btn-call:hover{transform:translateY(-3px)}
.card-call{border-radius:999px}
/* WhatsApp gets the exact same liquid-glass upgrade as Call, so the pair
   reads as one design, not two different button styles. */
.btn-whatsapp{
  border-radius:999px;padding:15px 30px;font-size:14.5px;letter-spacing:.02em;
  backdrop-filter:blur(22px) saturate(190%);-webkit-backdrop-filter:blur(22px) saturate(190%);
  border-width:1.5px;
  transition:transform .45s var(--ease-epic),box-shadow .45s var(--ease-epic),
             border-color .3s var(--ease),background .3s var(--ease);
}
.btn-whatsapp:hover{transform:translateY(-3px)}
.card-whatsapp{border-radius:999px}

/* ── 6. Cards — cursor-lit glass panes, corner-braced, floating on hover ─
   Every card family now tracks the pointer via the same --mx/--my the
   spotlight already writes, so the highlight sits exactly under the
   cursor — the one touch that makes glass feel physically present. */
.feature-card,.category-card,.product-card,.cta-band-inner,.pf-stat,
.gallery-card,.inq-card,.order-panel,.contact-note,.detail-desc{
  border-radius:var(--radius-lg);
  border-width:1.5px;
  transition:transform .55s var(--ease-epic),box-shadow .5s var(--ease-epic),border-color .35s var(--ease);
}
.feature-card::before{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:0;
  opacity:0;transition:opacity .45s var(--ease);
  background:radial-gradient(340px circle at var(--mx,50%) var(--my,50%),
    rgba(18,196,222,.16),transparent 70%);
}
.feature-card:hover::before,.category-card:hover::before{opacity:1}
.feature-card:hover,.category-card:hover,.product-card:hover,
.gallery-card:hover,.inq-card:hover{
  transform:translateY(-8px);
  border-color:rgba(18,196,222,.45);
}
.pf-stat:hover{transform:translateY(-4px)}
/* Corner braces — the registration-mark language, shrunk onto every card. */
.feature-card,.category-card,.product-card,.gallery-card,.cta-band-inner{position:relative}
.feature-card::after,.category-card::after,.product-card::after,.gallery-card::after,.cta-band-inner::after{
  --bl:16px;
}
.product-detail-image::before,.product-detail-image::after,
.label-demo::before,.label-demo::after{
  transition:box-shadow .5s var(--ease);
}

/* Chips — glass capsules with a lit rim */
.spec-chips span,.eyebrow-pill,.tab-pill{
  backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);
}

/* ── 7. Footer — the closing plinth, monumental version ──────────────────
   Deeper ink, a brighter seam, and glass panels for the contact links so
   the footer reads as one more lit surface rather than a flat end-cap. */
footer{padding:clamp(64px,7vw,96px) 0 clamp(36px,4vw,48px)}
footer::before{
  height:2px;
  background:linear-gradient(90deg,transparent,#4EE2F5,transparent);
  box-shadow:0 0 26px rgba(78,226,245,.8);
}
.footer-contact a{
  display:inline-flex;align-items:center;gap:9px;padding:10px 16px;border-radius:999px;
  background:rgba(255,255,255,.05);border:1px solid rgba(127,230,245,.22);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  transition:border-color .3s var(--ease),background .3s var(--ease),transform .3s var(--ease);
}
.footer-contact a:hover{border-color:var(--cyan-bright);background:rgba(127,230,245,.1);transform:translateY(-2px)}
.footer-grid .brand{text-shadow:0 0 30px rgba(18,196,222,.25)}

/* The bottom row as one glass strip, instead of two lines of text floating
   on bare ink — a copyright line is not decoration, but it reads better
   sitting on something. */
.footer-bottom{
  position:relative;margin-top:8px;padding:16px 22px !important;border-radius:16px;
  background:rgba(255,255,255,.04);border:1px solid rgba(127,230,245,.14);border-top:1px solid rgba(127,230,245,.14) !important;
  backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%);
}

/* Back-to-top floating button: removed site-wide by request. Only the
   chat widget (WhatsApp fab + chat bubble) remains in the bottom-right
   corner, styled exactly as it already was. */

/* ── 8. Forms — glass fields with a lit focus ring ───────────────────────
   Contact and admin inputs get the same frosted material as the cards,
   so the whole page — not just its cards — feels machined from one glass. */
.contact-form input,.contact-form textarea{
  border-radius:var(--radius);border-width:1.5px;
  background:var(--field-bg);
  backdrop-filter:blur(14px) saturate(180%);-webkit-backdrop-filter:blur(14px) saturate(180%);
  transition:border-color .3s var(--ease),box-shadow .3s var(--ease),background .3s var(--ease);
}
.contact-form input:focus,.contact-form textarea:focus{
  box-shadow:var(--ring),0 0 30px -14px rgba(18,196,222,.5);
  background:var(--paper);
}

/* ── 9. Page hero (Products / Gallery / Contact) — same monumental floor
   the home hero stands on, brought to the white pages. ──────────────────── */
.page-hero{padding:clamp(70px,7.5vw,116px) 0 clamp(48px,5vw,72px)}
.page-hero::before{
  background:
    radial-gradient(1100px 520px at 84% -34%, rgba(18,196,222,.18), transparent 62%),
    radial-gradient(700px 420px at 8% 10%, rgba(7,151,174,.09), transparent 60%),
    linear-gradient(rgba(7,151,174,.06) 1px,transparent 1px),
    linear-gradient(90deg,rgba(7,151,174,.06) 1px,transparent 1px);
  background-size:auto, auto, 78px 78px, 78px 78px;
}
.breadcrumb{
  padding:7px 16px;border-radius:999px;
  background:var(--card-bg-2);border:1px solid var(--card-border);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  width:fit-content;
}

/* ── 10. Product detail — pushed one more level past the v2 pass ────────
   A brighter atmosphere ring, a specimen frame with a slow internal glint,
   a price that reads like a marquee number, and an order panel with
   layered corner braces to match the rest of the card family. */
.section[data-page="product-detail"]::after{
  width:74%;filter:blur(86px);
  background:radial-gradient(circle,rgba(18,196,222,.26),transparent 66%);
}
.product-detail-image{border-radius:var(--radius-xl)}
.product-detail-image::before{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:2;
  background:linear-gradient(120deg,transparent 30%,rgba(255,255,255,.35) 46%,transparent 62%);
  background-size:220% 220%;
  animation:glintSweep 7s var(--ease-epic) infinite;
  mix-blend-mode:overlay;
}
@keyframes glintSweep{
  0%,100%{background-position:120% -20%}
  50%{background-position:-20% 120%}
}
.order-price{
  font-size:clamp(38px,4.5vw,56px);
  text-shadow:0 0 70px rgba(18,196,222,.6),0 0 20px rgba(78,226,245,.55);
}
.order-panel{border-radius:var(--radius-xl)}

@media (prefers-reduced-motion: reduce){
  .product-detail-image::before{animation:none}
}

/* ── 11. Reveal-in — a touch more cinematic than a plain fade ────────────
   Rises and softly de-blurs into place instead of only fading, without
   touching the class app.js toggles. */
.js .reveal{filter:blur(6px);transition:opacity .8s var(--ease-out),transform .8s var(--ease-out),filter .9s var(--ease-out)}
.reveal.in-view,.reveal-all .reveal{filter:blur(0)}

@media print{
  .hero::after{display:none !important}
}

/* ═══════════════════════════════════════════════════════════════════════
   CHAT — CONVERSATION HISTORY & COMPOSER, A PREMIUM PASS
   ---------------------------------------------------------------------------
   The bubble, panel and header already got their "machined instrument"
   finish above (§7) and their glass upgrade in the v2/v3 layers. This pass
   is about what happens ONCE the panel is open: the thread itself should
   read the way ChatGPT / Gemini / Claude's own history does — grouped by
   day, timestamped, sender bursts collapsed into one turn instead of a
   label per line, new messages arriving with a soft lift instead of a
   hard cut, and a composer that grows with what you're typing instead of
   scrolling sideways inside one fixed-height line.

   Nothing here touches the privacy behaviour in chat.js (a fresh page load
   still starts empty on a shared computer, History still has to be
   tapped) — this only changes how that same data is drawn.

   Appended last, so it wins the cascade with zero !important.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── The composer — an auto-growing textarea, not a fixed single line ──
   Enter sends, Shift+Enter starts a new line (see chat.js); this is just
   the shape it grows into as chat.js adjusts its height. */
.chat-input-row{align-items:flex-end}
.chat-input-row textarea{
  flex:1;min-width:0;resize:none;
  height:44px;min-height:44px;max-height:116px;
  padding:11px 15px;border-radius:var(--radius);
  border:1px solid var(--line-strong);background:var(--field-bg,var(--paper));
  font-size:14.5px;line-height:1.5;color:var(--ink);font-family:var(--font-body);
  transition:border-color .22s var(--ease),box-shadow .22s var(--ease);
}
.chat-input-row textarea::placeholder{color:var(--muted)}
.chat-input-row textarea:focus{outline:none;border-color:var(--cyan);box-shadow:var(--ring)}
.chat-send{align-self:flex-end;transition:filter .22s var(--ease),transform .22s var(--ease),opacity .22s var(--ease)}
.chat-send:disabled{opacity:.4;cursor:not-allowed;transform:none !important;filter:none !important}

/* ── The body becomes a positioning shell, so a "jump to latest" button
   can float over it without disturbing the flex column beneath (head,
   body, suggestions, input row). ─────────────────────────────────────── */
.chat-body-wrap{position:relative;flex:1;min-height:0;display:flex}
.chat-body-wrap .chat-body{flex:1}

.chat-scroll-btn{
  position:absolute;right:14px;bottom:14px;z-index:2;width:34px;height:34px;
  border-radius:50%;display:grid;place-items:center;cursor:pointer;
  background:var(--card-bg-2,var(--paper));border:1px solid var(--card-border,var(--line-strong));
  color:var(--cyan-ink);box-shadow:var(--shadow);
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
  opacity:0;visibility:hidden;transform:translateY(8px) scale(.92);
  transition:opacity .22s var(--ease),transform .22s var(--ease),visibility .22s,border-color .22s var(--ease),color .22s var(--ease);
}
.chat-scroll-btn.show{opacity:1;visibility:visible;transform:none}
.chat-scroll-btn:hover{border-color:var(--cyan);color:var(--cyan)}
.chat-scroll-btn svg{display:block}

/* ── Your conversations panel — a small ChatGPT/Claude-style thread list
   that slides over the message body without disturbing the header or the
   composer beneath it. ──────────────────────────────────────────────── */
.chat-threads-panel{
  position:absolute;inset:0;z-index:3;display:flex;flex-direction:column;
  background:var(--paper);
}
.chat-threads-head{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 16px 10px;font-family:var(--font-display);font-weight:700;font-size:14px;color:var(--ink);
}
.chat-threads-close{
  width:28px;height:28px;border-radius:var(--radius-sm);flex:none;
  border:1px solid var(--line);background:transparent;color:var(--ink-2);
  cursor:pointer;display:grid;place-items:center;transition:background .2s,color .2s;
}
.chat-threads-close:hover{background:var(--soft);color:var(--ink)}
.chat-thread-new{
  margin:0 16px 10px;display:flex;align-items:center;justify-content:center;gap:8px;
  padding:10px 14px;border-radius:var(--radius);cursor:pointer;
  font-family:var(--font-display);font-weight:700;font-size:13.5px;
  background:linear-gradient(180deg,#4EE2F5,#12C4DE);color:var(--on-cyan);border:none;
  transition:filter .2s;
}
.chat-thread-new:hover{filter:brightness(1.06)}
.chat-thread-list{flex:1;overflow-y:auto;padding:0 10px 12px;display:flex;flex-direction:column;gap:4px}
.chat-thread-item{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  width:100%;text-align:left;padding:11px 12px;border-radius:var(--radius-sm);
  background:transparent;border:1px solid transparent;cursor:pointer;
  transition:background .2s,border-color .2s;
}
.chat-thread-item:hover{background:var(--soft)}
.chat-thread-item.active{background:var(--soft);border-color:var(--line-strong)}
.chat-thread-preview{
  font-size:13.5px;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.chat-thread-item.active .chat-thread-preview{color:var(--ink);font-weight:600}
.chat-thread-when{font-family:var(--font-mono);font-size:10.5px;color:var(--muted);flex:none}

/* ── Day dividers — "Today / Yesterday / 12 Aug", centred and quiet ────── */
.chat-date-sep{
  align-self:stretch;display:flex;align-items:center;gap:10px;
  margin:6px 0 2px;color:var(--muted);
  font-family:var(--font-mono);font-size:9.5px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;
}
.chat-date-sep::before,.chat-date-sep::after{content:"";flex:1;height:1px;background:var(--line)}

/* ── The "you're viewing full history" marker — shown once, the first
   message in from before this page load, only while History is open. ── */
.chat-history-marker{
  align-self:center;display:flex;align-items:center;gap:6px;
  margin:0 0 8px;padding:6px 14px;border-radius:999px;
  background:var(--cyan-wash);color:var(--cyan-ink);
  border:1px solid rgba(7,151,174,.18);
  font-family:var(--font-mono);font-size:9.5px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;
}

/* ── Sender bursts — the avatar + name only repeats when the sender
   actually changes, so three replies in a row read as one turn. Grouped
   bubbles sit closer together than a fresh turn does. ──────────────────── */
.chat-msg.grouped{margin-top:-6px}
.chat-msg-meta{display:flex;align-items:center;gap:7px;margin-bottom:1px}
.chat-msg-avatar{
  width:19px;height:19px;flex:none;border-radius:50%;display:grid;place-items:center;
  font-family:var(--font-mono);font-size:8px;font-weight:700;letter-spacing:.01em;
}
.chat-msg-avatar.ai{background:linear-gradient(180deg,#4EE2F5,#12C4DE);color:var(--on-cyan)}
.chat-msg-avatar.admin{background:linear-gradient(180deg,#0D2531,#06171F);color:#fff}

/* ── A quiet timestamp under every bubble — right-aligned for the
   visitor's own messages, left-aligned for the reply, exactly like the
   thread it's modelled on. ──────────────────────────────────────────── */
.chat-msg-time{
  font-family:var(--font-mono);font-size:9px;color:var(--muted);opacity:.8;
}

/* ── New bubbles arrive with a soft lift, not a hard cut. Only messages
   chat.js has never painted before get this class, so scrolling or a
   background snapshot never replays it across the whole thread. ──────── */
@keyframes chatMsgIn{
  from{opacity:0;transform:translateY(7px) scale(.985)}
  to{opacity:1;transform:none}
}
.chat-msg-enter{animation:chatMsgIn .32s var(--ease-out,var(--ease)) both}

/* ── Starter chips arrive with a small stagger instead of popping in as
   one block. ─────────────────────────────────────────────────────────── */
@keyframes chatChipIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.chat-suggest button{opacity:0;animation:chatChipIn .3s var(--ease-out,var(--ease)) both}
.chat-suggest button:nth-child(1){animation-delay:.02s}
.chat-suggest button:nth-child(2){animation-delay:.07s}
.chat-suggest button:nth-child(3){animation-delay:.12s}
.chat-suggest button:nth-child(4){animation-delay:.17s}

/* ── A quiet breathing glow on the header avatar and a slightly springier
   open, so the panel feels less like a modal snapping open and more like
   a surface arriving. ─────────────────────────────────────────────────── */
@keyframes chatAvatarGlow{
  from{box-shadow:0 0 20px -6px rgba(18,196,222,.85)}
  to{box-shadow:0 0 28px -4px rgba(18,196,222,1)}
}
.chat-avatar{animation:chatAvatarGlow 3.2s var(--ease-soft,var(--ease)) infinite alternate}
.chat-panel{transition:opacity .3s var(--ease),transform .4s cubic-bezier(.34,1.56,.64,1),visibility .3s}

/* ── The bubble pulses gently while something's waiting to be read,
   the same notification language the rest of the site uses. ──────────── */
@keyframes chatBubblePulse{
  0%{transform:scale(.92);opacity:.85}
  70%,100%{transform:scale(1.38);opacity:0}
}
.chat-bubble.has-unread::before{
  content:"";position:absolute;inset:-6px;z-index:-1;border-radius:inherit;
  border:2px solid rgba(18,196,222,.55);
  animation:chatBubblePulse 1.9s var(--ease) infinite;
}

@media (prefers-reduced-motion: reduce){
  .chat-msg-enter,.chat-suggest button,.chat-avatar,.chat-bubble.has-unread::before{animation:none !important}
  .chat-msg-enter{opacity:1;transform:none}
  .chat-suggest button{opacity:1}
  .chat-panel{transition:opacity .01s linear,visibility .01s linear}
}

@media (max-width:480px){
  /* One line of chip text less to scroll past on a narrow phone keyboard
     view — the composer's own growth already eats the same space. */
  .chat-input-row textarea{max-height:96px}
}

/* ═══════════════════════════════════════════════════════════════════════
   CHATBOX — EPIC CINEMATIC UPGRADE
   ---------------------------------------------------------------------------
   The rest of the site already runs the "dark band under white paper"
   showroom logic (see the note at the top of this file) and the v2 glass
   layer above turned that into real frosted glass everywhere. The widget
   itself was left in its first, flatter pass: a plain dark header sat on a
   flat --soft body with no glass, no ambient glow, no depth. This section
   brings the chat bubble in line with everything around it — one more
   light-and-dark material, lit like the rest of the room, appended last so
   it wins the cascade without a single !important. Nothing here removes a
   class or a behaviour; every selector chat.js already writes keeps
   working exactly as before. ═══════════════════════════════════════════ */

/* An ambient cyan atmosphere breathing behind the whole widget — the same
   trick the hero and the gallery band use, at chat-bubble scale. Sits
   behind everything (z-index -1) and never intercepts a click. */
.chat-widget::before{
  content:"";position:absolute;right:-40px;bottom:-40px;width:260px;height:260px;
  background:radial-gradient(circle,rgba(18,196,222,.32),transparent 70%);
  filter:blur(30px);pointer-events:none;z-index:-1;
  opacity:0;transition:opacity .5s var(--ease);
}
.chat-widget:has(.chat-panel.open)::before{opacity:1}

/* The launcher: a real machined lamp, not a flat circle. A slow, always-on
   breathing ring (independent of the unread-pulse, which still layers on
   top) plus a glassy top highlight. */
.chat-bubble{
  position:relative;overflow:visible;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.chat-bubble::after{
  content:"";position:absolute;inset:-3px;z-index:-1;border-radius:inherit;
  background:conic-gradient(from 180deg,rgba(18,196,222,.55),rgba(78,226,245,.15),rgba(18,196,222,.55));
  opacity:.55;filter:blur(7px);
  animation:chatLampBreathe 4.2s var(--ease-soft,var(--ease)) infinite;
}
@keyframes chatLampBreathe{
  0%,100%{opacity:.35;transform:scale(.97)}
  50%{opacity:.7;transform:scale(1.04)}
}
@media (prefers-reduced-motion: reduce){ .chat-bubble::after{animation:none} }

/* The small WhatsApp launcher above it gets the same machined-lamp
   treatment — matched radius, glass blur, breathing glow ring — just in
   WhatsApp's own green, so the two read as one lit pair instead of one
   upgraded button sitting next to a flat leftover one. */
.chat-whatsapp-fab{
  position:relative;overflow:visible;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.chat-whatsapp-fab::after{
  content:"";position:absolute;inset:-3px;z-index:-1;border-radius:inherit;
  background:conic-gradient(from 180deg,rgba(37,211,102,.6),rgba(79,227,155,.18),rgba(37,211,102,.6));
  opacity:.5;filter:blur(6px);
  animation:chatLampBreathe 4.2s var(--ease-soft,var(--ease)) infinite;
}
@media (prefers-reduced-motion: reduce){ .chat-whatsapp-fab::after{animation:none} }

/* The panel itself: frosted glass over the dark/light materials that were
   already there, wrapped in a soft gradient rim and a wider ambient glow
   than the flat shadow it had before. */
.chat-panel{
  backdrop-filter:var(--glass,blur(20px) saturate(180%));
  -webkit-backdrop-filter:var(--glass,blur(20px) saturate(180%));
  border-color:rgba(127,230,245,.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    var(--shadow-lg),
    0 0 90px -30px rgba(18,196,222,.55),
    0 0 0 1px rgba(18,196,222,.12);
}

/* Header: the dark band gets a slow-moving sheen across it, like light
   sweeping a lacquered surface — cinematic, not distracting, and it stops
   for anyone who asked for reduced motion. */
.chat-head{
  background-size:220% 220%;
  animation:chatHeadSheen 9s var(--ease-soft,var(--ease)) infinite;
}
@keyframes chatHeadSheen{
  0%,100%{background-position:0% 0%}
  50%{background-position:100% 60%}
}
@media (prefers-reduced-motion: reduce){ .chat-head{animation:none} }

/* Body: still light, on purpose — a wall of dark bubbles is exhausting to
   read — but no longer a flat tint. A faint cyan wash in the top corner and
   the same film-grain the dark bands use (at whisper strength) give it the
   same "lit room" depth as the rest of the page, while staying legible. */
.chat-body{
  background-color:var(--soft);
  background-image:var(--grain-soft),
    radial-gradient(120% 70% at 100% 0%,rgba(18,196,222,.10),transparent 60%),
    radial-gradient(90% 60% at 0% 100%,rgba(7,151,174,.06),transparent 60%);
  background-blend-mode:overlay,normal,normal;
}
/* A slim, lit scroll channel instead of the browser default — the same
   language as .scroll-rail elsewhere on the site. */
.chat-body{scrollbar-width:thin;scrollbar-color:rgba(7,151,174,.45) transparent}
.chat-body::-webkit-scrollbar{width:6px}
.chat-body::-webkit-scrollbar-thumb{background:rgba(7,151,174,.4);border-radius:99px}
.chat-body::-webkit-scrollbar-thumb:hover{background:rgba(7,151,174,.65)}

/* Message bubbles: more glass, more depth, still exactly the same markup
   chat.js already produces. */
.chat-empty,
.chat-msg.ai .chat-msg-text,.chat-msg.admin .chat-msg-text,
.chat-dots{
  background:rgba(255,255,255,.72);
  backdrop-filter:blur(10px) saturate(160%);-webkit-backdrop-filter:blur(10px) saturate(160%);
  border-color:rgba(7,151,174,.18);
  box-shadow:0 6px 18px -14px rgba(6,23,31,.4),inset 0 1px 0 rgba(255,255,255,.9);
}
.chat-msg.me .chat-msg-text{
  background:linear-gradient(160deg,#4EE2F5 0%,#12C4DE 46%,#0797AE 100%);
  box-shadow:
    0 10px 26px -14px rgba(7,151,174,.85),
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -10px 18px -12px rgba(4,96,116,.55);
}
.chat-msg-enter{will-change:opacity,transform}

/* Suggestion chips and the composer pick up the same glass, so the whole
   panel reads as one material rather than three different eras of the
   file stacked on top of each other. */
.chat-suggest button{
  background:rgba(255,255,255,.65);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
}
.chat-suggest button:hover{
  box-shadow:0 8px 18px -12px rgba(7,151,174,.5);
  transform:translateY(-1px);
}
.chat-input-row{
  background:rgba(255,255,255,.6);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
.chat-input-row textarea{background:rgba(255,255,255,.7)}
.chat-input-row textarea:focus{box-shadow:var(--ring),0 0 22px -10px rgba(18,196,222,.6)}
.chat-send{box-shadow:0 8px 20px -12px rgba(7,151,174,.7)}
.chat-send:hover{box-shadow:0 10px 26px -12px rgba(7,151,174,.85)}

/* Fallback for the handful of browsers with no backdrop-filter support at
   all: fall back to a solid surface rather than a see-through panel with
   no legible background underneath it. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .chat-panel,.chat-body,.chat-input-row,.chat-suggest button,
  .chat-empty,.chat-msg.ai .chat-msg-text,.chat-msg.admin .chat-msg-text,.chat-dots{
    background:var(--paper) !important;
  }
}
