/* ==========================================================================
   Locksmiths Canada — character layer

   Loads after lc-design.css and only adds. Delete this file and the site
   returns exactly to the base system.

   The idea: this is a printed price card from a locksmith's counter, not a
   SaaS dashboard. Four devices carry it, used sparingly — a key-bitting rule,
   dot leaders on every price, a registry stamp, and hard offset shadows
   instead of soft blur. Nothing decorative that does not also mean something.

   --------------------------------------------------------------------------
   EDIT HERE FIRST

   Everything you are likely to want to change lives in the block below.
   Change a number, save, reload. Nothing else in this file needs touching.
   Each one says what it does and what a sensible range is.
   -------------------------------------------------------------------------- */

:root{

  /* Depth of the hard offset shadow under the fee card, the highlighted plan
     and the search box. 0 removes them entirely. Sensible: 0 to 12px. */
  --ink-shadow:9px;
  --ink-shadow-sm:5px;

  /* How far off-square the fee card sits in the hero. 0deg makes it straight.
     Anything past 1.5deg starts to look like a mistake. Sensible: 0 to 1deg. */
  --card-tilt:-.55deg;

  /* How far the fee card drops below the headline. 0 lines them up. */
  --card-drop:52px;

  /* Strength of the registry stamp. 0 hides it, 1 is full ink. */
  --stamp-ink:.42;

  /* Strength of the paper grain over the whole page. 0 removes the texture.
     Sensible: 0 to .06 — above that it starts to fight the text. */
  --grain:.028;

  /* Hover lift and shadow speed. Sensible: .12s to .3s. */
  --lift:.18s;

  /* Corner radius and label size of every image placeholder. */
  --ph-radius:var(--r-l);

}

/* --- 1. Paper -------------------------------------------------------------
   A faint fibre grain over everything, strength set by --grain above.
   It sits in a fixed overlay so it does not scroll with the content and does
   not multiply across long pages. pointer-events:none keeps it click-through. */
body::before{
  content:"";position:fixed;inset:0;z-index:1;pointer-events:none;
  opacity:var(--grain);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- 1b. Image placeholders ----------------------------------------------
   A slot that reserves the exact space a real photograph will take, so
   swapping one in never shifts the layout.

   HOW TO USE
     <div class="ph-slot" data-label="Locksmith at a door"></div>

   HOW TO REPLACE WITH A REAL PHOTO
     <div class="ph-slot"><img src="..." alt="Describe what is happening"></div>
     The dashed frame and the label disappear on their own once an img is
     inside. Nothing else to change.

   SHAPE
     Add one of ph-slot--wide (16:9), --square (1:1) or --tall (3:4).
     Default is 3:2. Or set --ph-ratio inline for a one-off. */
.ph-slot{
  position:relative;display:block;width:100%;overflow:hidden;
  border-radius:var(--ph-radius);
  border:1px dashed var(--rule);
  background:var(--paper2);
}
.ph-slot::before{content:"";display:block;padding-top:var(--ph-ratio,66.667%)}
.ph-slot--wide{--ph-ratio:56.25%}
.ph-slot--square{--ph-ratio:100%}
.ph-slot--tall{--ph-ratio:133.333%}

/* the label, plus crop marks in the corners so an empty slot still reads as
   a deliberate frame rather than a broken image */
.ph-slot::after{
  content:attr(data-label);
  position:absolute;inset:0;display:grid;place-items:center;
  padding:16px;text-align:center;
  font-family:'IBM Plex Mono',monospace;font-size:10.5px;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink30);
  background:
    linear-gradient(var(--ink30),var(--ink30)) 12px 12px/14px 1px no-repeat,
    linear-gradient(var(--ink30),var(--ink30)) 12px 12px/1px 14px no-repeat,
    linear-gradient(var(--ink30),var(--ink30)) right 12px bottom 12px/14px 1px no-repeat,
    linear-gradient(var(--ink30),var(--ink30)) right 12px bottom 12px/1px 14px no-repeat;
}
.ph-slot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.ph-slot:has(img){border:none;background:none}
.ph-slot:has(img)::after{display:none}

/* a row of slots, used on the home page */
.ph-row{display:grid;grid-template-columns:repeat(3,1fr);gap:11px}
@media(max-width:700px){.ph-row{grid-template-columns:1fr}}


/* --- 2. The bitting rule --------------------------------------------------
   The cut profile of a key blade. Sits under every section heading in place
   of a generic underline. On a service page it is that service's OWN cut,
   handed in as --cut by lc-icons.php. Elsewhere it falls back to a generic
   blade. Small enough to read as a mark, not an illustration. */
:root{--cut-generic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='12' viewBox='0 0 96 12'%3E%3Cpath d='M0 12V5h10V2h12v5h10V3h12v5h12V4h12v3h12V2h16v10z' fill='%23B5763A'/%3E%3C/svg%3E")}

.sh{position:relative;padding-bottom:18px}
.sh::after{
  content:"";position:absolute;left:0;bottom:0;width:96px;height:12px;
  background:var(--cut,var(--cut-generic)) no-repeat left bottom;background-size:96px 12px;
}

/* Each service card wears its own cut under its name. Eight services, eight
   blades, generated from the slug so they never drift. */
.sv__n::after{
  content:"";display:block;width:72px;height:9px;margin-top:8px;opacity:.8;
  background:var(--cut,var(--cut-generic)) no-repeat left bottom;background-size:72px 9px;
}

/* --- 2b. Margin running heads --------------------------------------------
   The 100px gutters are dead space on desktop. A technical manual would put
   the section index there, set vertically, with a hairline running down from
   it. Numbering is automatic — nothing to maintain in the markup. */
@media(min-width:981px){
  body{counter-reset:lcsec}
  .sec{counter-increment:lcsec}
  .sec>.wrap{position:relative}
  .sec>.wrap::before{
    content:counter(lcsec,decimal-leading-zero);
    position:absolute;left:34px;top:2px;
    font-family:'IBM Plex Mono',monospace;font-size:10px;font-weight:600;
    letter-spacing:.3em;color:var(--ink30);
    writing-mode:vertical-rl;
  }
  .sec>.wrap::after{
    content:"";position:absolute;left:39px;top:46px;width:1px;height:60px;
    background:linear-gradient(var(--rule),transparent);
  }
}

/* --- 2c. Docket perforation -----------------------------------------------
   The fee panel is torn from the listing, not bordered off it. */
.lc__fee{border-right:none;position:relative}
.lc__fee::after{
  content:"";position:absolute;top:0;bottom:0;right:-1px;width:2px;
  background-image:radial-gradient(circle,var(--rule) 1px,transparent 1px);
  background-size:2px 7px;background-repeat:repeat-y;
}
@media(max-width:700px){
  .lc__fee{border-bottom:1px solid var(--rule)}
  .lc__fee::after{display:none}
}

/* --- 2d. Tear-off edge ----------------------------------------------------
   The fee card ends in a torn stub, the way a price slip does. */
.fee{position:relative;border-bottom-left-radius:0;border-bottom-right-radius:0;padding-bottom:34px}
.fee::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:11px;
  background:radial-gradient(circle at 7px 11px,var(--paper) 5.5px,transparent 6px) repeat-x;
  background-size:14px 11px;
}

/* --- 2e. The 404 as a receipt --------------------------------------------- */
.lc-doc--404 .empty{
  max-width:430px;margin-inline:auto;border:none;border-radius:0;
  border-top:2px dashed var(--rule);border-bottom:2px dashed var(--rule);
  background:var(--card);
}
.lc-doc--404 .empty h3{
  font-family:'IBM Plex Mono',monospace;font-size:14px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;
}
.lc-doc--404 .empty p{font-family:'IBM Plex Mono',monospace;font-size:12.5px}


/* --- 3. Dot leaders -------------------------------------------------------
   Label ········ $95–140. How a printed price list sets a row, and it makes the
   number the thing your eye lands on. The dots are a background on the row;
   the label and the figure sit on opaque chips that mask them. */
.pr,.fr{background-image:radial-gradient(circle,var(--rule) 1.1px,transparent 1.1px);
  background-position:left 1.05em;background-size:7px 7px;background-repeat:repeat-x}
.pr>span,.pr>b{background:var(--card);position:relative}
.pr>span{padding-right:7px}
.pr>b{padding-left:7px}

/* on the dark fee card the dots and the chips invert */
.fr{background-image:radial-gradient(circle,rgba(255,255,255,.22) 1.1px,transparent 1.1px)}
.fr__l,.fr__v{background:var(--steel);position:relative}
.fr__l{padding-right:8px}
.fr__v{padding-left:8px}

/* --- 4. The registry stamp ------------------------------------------------
   The verified block gets an inked stamp rather than a green tick pill.
   Slightly off-square, because a stamp never lands straight. */
.vb{position:relative;overflow:hidden}
.vb::after{
  content:"REGISTRY CHECKED";
  position:absolute;top:12px;right:-6px;
  font-family:'IBM Plex Mono',monospace;font-size:8.5px;font-weight:600;
  letter-spacing:.18em;color:var(--ok);
  padding:5px 9px;border:1.5px solid var(--ok);border-radius:3px;
  box-shadow:inset 0 0 0 1px rgba(20,122,82,.25);
  transform:rotate(-4deg);opacity:var(--stamp-ink);pointer-events:none;
}
@media(max-width:700px){.vb::after{display:none}}

/* --- 5. Hard shadows ------------------------------------------------------
   Offset ink, no blur. A blurred drop shadow is the single most generic
   surface treatment on the web; a hard offset reads as printed stock. */
.fee{box-shadow:var(--ink-shadow) var(--ink-shadow) 0 var(--steel-lt)}
.pl--hi{box-shadow:var(--ink-shadow-sm) var(--ink-shadow-sm) 0 var(--cu-lt)}
.find{box-shadow:var(--ink-shadow-sm) var(--ink-shadow-sm) 0 var(--paper2)}

/* --- 6. Asymmetry ---------------------------------------------------------
   The fee card drops below the headline baseline and sits a fraction off
   true, like a card set down on the page rather than placed in a grid slot. */
@media(min-width:981px){
  .hero__g>.fee{margin-top:var(--card-drop);transform:rotate(var(--card-tilt))}
  .hero__g>.fee:hover{transform:rotate(0deg)}
}
.fee{transition:transform var(--lift) ease}

/* --- 7. Service icons -----------------------------------------------------
   Line icons replace the emoji. Copper, 1.6px stroke, same geometry as the
   bitting rule. */
.sv__i{display:block;width:22px;height:22px;color:var(--cu);margin-bottom:9px}
.sv__i svg{width:100%;height:100%;display:block}
.sv:hover .sv__i{color:var(--cu2)}

/* --- 8. Interaction -------------------------------------------------------
   Lift plus a shadow that grows in the same direction as the ink offset,
   180ms. Focus rings stay exactly as the base system defines them. */
.pv,.sv,.gc{transition:transform var(--lift) ease,box-shadow var(--lift) ease,border-color var(--lift) ease}
.pv:hover,.sv:hover,.gc:hover{box-shadow:4px 4px 0 var(--paper2)}
.lc{transition:border-color var(--lift) ease,box-shadow var(--lift) ease}
.lc:hover{box-shadow:5px 5px 0 var(--paper2)}
.lc--top{box-shadow:inset 3px 0 0 var(--cu)}

/* --- 9. Numerals ----------------------------------------------------------
   Every figure on the site is a claim someone made on a date. Slashed zero
   and tabular figures so a column of prices lines up and cannot be misread. */
.mono,.lc__fee b,.fr__v,.pl__p,.kp__v,.stat__n,.cmp__f{
  font-variant-numeric:tabular-nums slashed-zero;
}

@media(prefers-reduced-motion:reduce){
  .hero__g>.fee,.fee,.pv,.sv,.gc,.lc{transition:none}
  @media(min-width:981px){.hero__g>.fee{transform:none}}
}

/* --- 10. The live map -----------------------------------------------------
   Leaflet replaces the drawn grid that stood in for a map. The frame stays
   in the house style: paper card, hard rule, copper pins from .pin.
   Height lives here so it can be changed without touching PHP. */
.map--live{background:var(--card);border:1px solid var(--rule);border-radius:var(--r-l);overflow:hidden}
.map--live .map__c{height:300px;background:var(--paper2) none;position:relative}
@media(max-width:980px){.map--live .map__c{height:240px}}
/* Leaflet injects its own chrome; bring it onto the palette. */
.map--live .leaflet-container{font-family:'Inter Tight',sans-serif;background:var(--paper2)}
.map--live .leaflet-control-attribution{background:rgba(255,255,255,.86);font-size:10px;color:var(--ink60)}
.map--live .leaflet-control-attribution a{color:var(--cu)}
.map--live .leaflet-bar a{color:var(--ink);border-bottom-color:var(--rule)}
.map--live .leaflet-bar a:hover{background:var(--paper)}
/* the divIcon wrapper must not paint over the pin itself */
.lc-pin-wrap{background:none;border:none}
.map--live .leaflet-popup-content-wrapper{border-radius:var(--r-m);box-shadow:var(--ink-shadow-sm) var(--ink-shadow-sm) 0 rgba(34,50,63,.14)}
.map--live .leaflet-popup-content{margin:11px 14px;font-size:13px;line-height:1.5}
.map--live .leaflet-popup-content a{color:var(--cu);font-weight:600}
