/* ==========================================================================
   pvcpools.ca
   1. Tokens
   2. Base
   3. Background
   4. App shell / screens
   5. Header (brand + nav chips)
   6. Home screen (tiles, footline)
   7. Inner screens (cards, lists, buttons)
   8. Gallery and administration
   9. Lightbox
   10. Desktop  <- the only place the phone layout is re-shaped
   ========================================================================== */

/* 1. Tokens ---------------------------------------------------------------- */
:root{
  --bg:#03080f;
  --ink:#eaf2ff;
  --sub:#93a8bd;
  --accent:#2f7bff;
  --line:rgba(160,195,255,0.22);
  --card:rgba(8,20,40,0.46);

  /* every size on the home screen is a fraction of --u, so the whole layout
     scales as one block instead of drifting apart between devices */
  --u:min(100vw,520px,49vh);

  --pad-t:calc(env(safe-area-inset-top) + 8px);
  --pad-r:calc(env(safe-area-inset-right) + 16px);
  --pad-b:max(env(safe-area-inset-bottom),12px);
  --pad-l:calc(env(safe-area-inset-left) + 16px);

  --screen-w:520px;
  /* the width the app is really laid out in — never the window on a desktop */
  --panel-raw:min(100vw, var(--screen-w));
  --panel:var(--panel-raw);
  --screen-h:100%;
  --screen-radius:0;
}

/* 2. Base ------------------------------------------------------------------ */
*{box-sizing:border-box}
html,body{
  height:100%;margin:0;overflow:hidden;overscroll-behavior:none;
  background:var(--bg);color:var(--ink);
  font-family:Barlow,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;
}
body{position:fixed;inset:0;touch-action:manipulation}
a{color:var(--accent);text-decoration:none}
[hidden]{display:none!important}

/* bilingual copy: both languages are in the DOM, CSS shows one */
.en,.fr{display:inline}
.fr{display:none}
.fr-on .fr{display:inline}
.fr-on .en{display:none}

/* 3. Background ------------------------------------------------------------ */
.bg{
  position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  background:radial-gradient(120% 80% at 50% -10%, #0d2745 0%, #071527 42%, #03080f 78%), var(--bg);
}
.bg-photo{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:var(--panel);height:calc(var(--panel) * 1.76667);
  object-fit:cover;object-position:50% 50%;transition:opacity 300ms ease;
}
/* What is left above and below the canvas continues the photograph's own edge row,
   one pixel tall and stretched down the band (img/bg-edge-*.png, built by
   _ref/build-bg-edges.js). Every column keeps its own colour, so the join is continuous
   instead of cutting a flat stripe across the pool. A gradient over the top settles it
   into the dark at the screen edge. The strips overlap the photo by 1px to cover the
   resampling seam. */
body.at-home-bg .bg::before,
body.at-home-bg .bg::after{content:"";position:absolute;left:0;right:0;background-size:100% 100%;background-repeat:no-repeat}
body.at-home-bg .bg::before{
  top:0;bottom:calc(50% + var(--panel) * 0.883335 - 1px);
  background-image:linear-gradient(180deg,rgba(4,8,12,0.92) 0%,rgba(4,8,12,0.35) 55%,rgba(4,8,12,0) 100%),
                   url('../../img/bg-edge-top.png');
}
body.at-home-bg .bg::after{
  top:calc(50% + var(--panel) * 0.883335 - 1px);bottom:0;
  background-image:linear-gradient(180deg,rgba(3,10,22,0) 0%,rgba(3,10,22,0.55) 45%,rgba(3,10,22,0.9) 100%),
                   url('../../img/bg-edge-bottom.png');
}
body.inner .bg-photo{opacity:0}
.vign{
  position:fixed;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(3,8,16,0.62) 0%, rgba(3,9,18,0.28) 22%, rgba(2,8,18,0.10) 46%,
    rgba(2,7,16,0.22) 78%, rgba(2,6,14,0.55) 100%);
}

/* 4. App shell ------------------------------------------------------------- */
.app{position:fixed;inset:0;height:100dvh;z-index:2;display:flex;flex-direction:column;width:100%;max-width:var(--screen-w);margin:0 auto}
.screens{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.screen{
  flex:1 1 auto;min-height:0;width:100%;
  /* the horizontal inset lives on .scroll, not here: overflow-y:auto clips at the
     padding box, and the footer has to reach wider than the content column */
  padding:0 0 var(--pad-b) 0;
  /* the inset of the content column, and the amount the footer steps back out of it.
     42 on the right is what the scroll bar needs: measured on a render, its stroke and
     its glow together run from 16 to 34px in from the edge. */
  --scroll-l:14px;
  --scroll-r:42px;
  display:flex;flex-direction:column;
}

/* 5. Header ----------------------------------------------------------------
   The brand block sits above a row of ten navigation chips, and that row is the
   navigation on every screen.

   Every number here was measured off the client's reference screenshot (IMG_2272,
   an iPhone 3x shot = a 390px viewport). They are written as a fraction of --hw,
   the app's own width, so the header is pixel-exact at 390px and scales instead of
   breaking on a 320px phone or inside the 340-440px desktop panel. The measuring
   script is PVC Pools/_ref/header-diff.js — run it before keeping a change here.
   -------------------------------------------------------------------------- */
:root{
  --hw:min(100vw,520px);        /* the width the header lays itself out against */
  --hdr-accent:#2c7bff;
  --hdr-edge:rgba(163,197,244,0.34);
}

.hdr{
  flex:0 0 auto;
  padding-top:env(safe-area-inset-top);
  background:linear-gradient(180deg,#04101f 0%,#07172f 26%,#091931 58%,#081c35 100%);
}

.hdr-brand{position:relative;height:calc(var(--hw)*0.13154)}
.hdr-mark{
  /* 0.01841 rather than the old 0.0215: the block is a little shorter than the image plus
     the live byline it replaced, and this keeps the lockup's optical centre where it was. */
  position:absolute;left:calc(var(--hw)*0.0282);top:calc(var(--hw)*0.01841);
  display:block;color:inherit;-webkit-tap-highlight-color:transparent;
}
/* The client's final lockup, one indivisible block — waves, wordmark and byline in the
   proportions his designer set. The width is chosen so PVC POOLS comes out the SAME size
   it was before (measured: 13.3 css px of cap height at --hw 390), not so the block keeps
   the old total width — the block now carries a byline the old raster did not, and
   matching total width would have quietly shrunk the words a person actually reads. */
.hdr-brandimg{display:block;width:calc(var(--hw)*0.3377);height:auto}
.langbtn{
  position:absolute;right:calc(var(--hw)*0.0368);top:calc(var(--hw)*0.042);
  background:none;border:0;padding:0 0 6px;
  font-family:Barlow,Helvetica,Arial,sans-serif;font-weight:500;
  font-size:calc(var(--hw)*0.02564);letter-spacing:0;line-height:1;
  color:#f5ffff;cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
/* the mockup underline: 1px, slightly shorter than the text, tucked to the right */
.langbtn::after{
  content:"";position:absolute;right:0;bottom:0;width:90%;height:1px;
  background:var(--hdr-accent);
}

.hdr-nav{display:flex;gap:calc(var(--hw)*0.00718);padding:0 calc(var(--hw)*0.01026)}
.navchip{
  flex:1 1 0;min-width:0;height:calc(var(--hw)*0.13846);
  border:1px solid rgba(150,180,220,0.42);border-radius:calc(var(--hw)*0.0162);background:#0a1c38;
  display:flex;flex-direction:column;align-items:center;
  padding:calc(var(--hw)*0.022) 0 0;
  color:#e7f1ff;font:inherit;cursor:pointer;overflow:hidden;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  transition:background 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
}
.navchip-ic{color:#eef2f8}
/* per-chip glyph sizes measured off the mockup; the container fits the tallest */
.navchip-ic{display:flex;align-items:center;justify-content:center;height:calc(var(--hw)*0.05179)}
.navchip[data-nav="home"] .navchip-ic svg{width:calc(var(--hw)*0.05667);height:calc(var(--hw)*0.05077)}
.navchip[data-nav="about"] .navchip-ic svg{width:calc(var(--hw)*0.05462);height:calc(var(--hw)*0.04795)}
.navchip[data-nav="work"] .navchip-ic svg{width:calc(var(--hw)*0.06154);height:calc(var(--hw)*0.04590)}
.navchip[data-nav="docs"] .navchip-ic svg{width:calc(var(--hw)*0.04205);height:calc(var(--hw)*0.05179)}
.navchip[data-nav="partners"] .navchip-ic svg{width:calc(var(--hw)*0.06051);height:calc(var(--hw)*0.04385)}
.navchip[data-nav="contacts"] .navchip-ic svg{width:calc(var(--hw)*0.04872);height:calc(var(--hw)*0.05179)}
/*
   A label too wide for its chip is NARROWED, not shrunk: Archivo carries a width axis, so
   the letters come in while the type stays the same height and the row still reads as one
   size. Measured on the live site at 320/360/390/430px before this existed: DOCUMENTS was
   over its chip by 2.0-2.7px at every width and was the only one over; MATERIALS, OUR WORK
   and WORK DETAILS had barely 2-3px to spare. The buckets are by character count because
   every chip is exactly the same width.
*/
.navchip-cap .is-long{font-variation-settings:'wdth' 84}
.navchip-cap .is-longer{font-variation-settings:'wdth' 76}
.navchip-cap .is-xlong{font-variation-settings:'wdth' 74;font-size:0.86em}
.navchip-cap{
  margin-top:calc(var(--hw)*0.0155);
  font-family:Archivo,Barlow,Helvetica,sans-serif;
  font-size:calc(var(--hw)*0.0148);font-weight:500;letter-spacing:0.012em;line-height:1;
  color:#f0f2f7;white-space:nowrap;
}
.navchip:hover{border-color:rgba(44,123,255,0.7);background:#0b2144}
.navchip:focus-visible{outline:2px solid var(--hdr-accent);outline-offset:2px}
.navchip.is-active{
  background:var(--hdr-accent);border-color:#82b1ff;color:#faffff;
  box-shadow:0 0 15px rgba(44,123,254,0.55);
}
.navchip.is-active .navchip-ic{color:#faffff}

/* 6. Home screen -----------------------------------------------------------
   Built to the owner's approved package (PVC_Pools_Homepage_Admin_Package, 2026-08-29):
   a 480x848 reference image plus a README that gives every coordinate. Its own words:
   "Use only the files in this package. Do not use earlier mockups."

   Corrected 2026-08-29 to the client's review, "исправления главной страницы". His
   finding, and it was right: the design is a 480x848 canvas — 1.76667 as tall as it is
   wide — and a phone is taller than that, so laying it out against the SCREEN stretched
   every vertical gap, pushed the top block under the status bar and left the nine tiles
   140px above where they belong. .home-stage restores the canvas and centres it; every
   number below is then a plain reference coordinate.

   --panel inside home is re-derived so the stage also fits a SHORT screen (landscape, a
   small desktop panel): it is the smaller of the panel width and the height the canvas
   can afford. Everything else in the file keeps the outer --panel.

   Reference geometry, in canvas pixels (measured, not guessed — see
   _ref/measure-ref-footer.js and _ref/home-diff.js):
     Francais       ink x 426..464, y 21..30 including its underline
     waves mark     ink 80 x 57 at x 63, y 43     (the PNG carries 7.5% of top padding)
     PVC POOLS      Archivo Italic 800, ink x 159..417, y 49..99
     tagline        ink x 62..417, y 100..124
     services line  ink x 86..393, y 146..155
     byline         group x 62..418, ink x 150..329, y 184..196
     tiles          105 x 108 at (70,272) (188,272) (306,272), rows also at 392 and 512
     icon           54 x 54 at tile +26,+13     label at tile +80, 12px white
     tile fill      rgba(3,15,37,0.52)          outline rgba(132,174,229,0.86) 1px, r 8
     Quality First  element 112 x 50 at x 313, y 684   (its ink x 320..403, y 699..719)
     rules          86 wide, x 55..140 and x 340..425, at y 760
     ACROSS CANADA  words x 155..297, 12px gap, maple leaf 12 x 14 at x 310..321
   Brand blue #3999FF.
   -------------------------------------------------------------------------- */

.screen[data-view="home"]{
  /* the canvas cannot be wider than the height allows, or a landscape phone would crop it */
  --panel:min(var(--panel-raw), calc(100dvh / 1.76667));
  position:relative;padding:0;
  display:flex;align-items:center;justify-content:center;
}
.home-stage{
  position:relative;flex:0 0 auto;
  width:var(--panel);height:calc(var(--panel) * 1.76667);   /* the 480 x 848 canvas */
}

.langbtn-home{
  position:absolute;right:calc(var(--panel)*0.03125);top:calc(var(--panel)*0.04375);
  background:none;border:0;padding:0 0 calc(var(--panel)*0.00208);
  font-family:Barlow,Helvetica,Arial,sans-serif;font-weight:500;line-height:1;
  font-size:calc(var(--panel)*0.02083);              /* 10px */
  color:#f5ffff;cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.langbtn-home::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:#3999FF;
}

/* the waves PNG has 7.5% of transparent padding on top, so the box starts at 38.3 for
   the ink to land on 43 */
.brand{
  position:absolute;left:0;right:0;top:calc(var(--panel)*0.07979);
  display:flex;flex-direction:column;align-items:center;text-align:center;
}

.brand-row{
  display:flex;align-items:center;justify-content:center;
  gap:calc(var(--panel)*0.03333);                    /* 16px between the mark and the P */
}
.brand-row img{
  width:calc(var(--panel)*0.16667);                  /* 80px of ink, full bleed in the file */
  height:auto;flex:0 0 auto;object-fit:contain;
  filter:drop-shadow(0 3px 14px rgba(0,0,0,0.55));
}
/* His final logo is the whole lockup in one file, so it takes the width the mark AND the
   wordmark used to take between them — measured at 321 of a 434 stage, which is 0.74. */
.brand-row .brand-logo{width:calc(var(--panel)*0.74)}
.wordmark{
  /* The only italic on the site, and it has a family to itself so that the italic file
     cannot be matched against anything else — see PVC Pools/_ref/no-italic-family.js. */
  font-family:'Archivo Wordmark',Archivo,Barlow,Helvetica,sans-serif;font-weight:800;font-style:italic;
  font-variation-settings:'wdth' 100;
  font-size:calc(var(--panel)*0.09167);              /* 44px */
  letter-spacing:-0.012em;line-height:0.95;white-space:nowrap;
  margin-top:calc(var(--panel)*0.01375);             /* the S sits on 99 with the waves */
}
.wm-a{color:#ffffff}
.wm-b{color:#3999FF}

/* an <h1> since 2026-09-16 — the margin is written in full so the browser's own h1
   margin-bottom cannot push the services line down */
.tagline{
  margin:calc(var(--panel)*0.00208) 0 0;
  font-size:calc(var(--panel)*0.0375);               /* 18px */
  font-weight:700;letter-spacing:0.006em;color:#ffffff;line-height:1.2;white-space:nowrap;
  text-shadow:0 1px 8px rgba(0,0,0,0.6);
}
.services-line{
  display:flex;align-items:center;justify-content:center;
  gap:calc(var(--panel)*0.0275);
  margin-top:calc(var(--panel)*0.04583);             /* to y 146 */
  font-size:calc(var(--panel)*0.02917);              /* 14px */
  font-weight:600;color:#3999FF;letter-spacing:0.064em;white-space:nowrap;
}
.bullet{
  width:calc(var(--panel)*0.01042);height:calc(var(--panel)*0.01042);
  border-radius:50%;background:#3999FF;flex:0 0 auto;
}

/* the rules reach the same edges as the logo above: the left of the waves and the right
   of the S in POOLS — x 62..418 on the reference canvas */
.byline{
  display:flex;align-items:center;gap:calc(var(--panel)*0.02708);
  width:calc(var(--panel)*0.74167);
  margin-top:calc(var(--panel)*0.04583);             /* to y 184 */
}
.byline .txt{
  font-size:calc(var(--panel)*0.0276);              /* matched to the reference ink, 180px */
  font-weight:400;letter-spacing:0.01em;color:#eaf1fb;white-space:nowrap;
}
.rule-l,.rule-r{flex:1 1 auto;height:1px;background:rgba(57,153,255,0.55)}

/* --- the nine tiles ------------------------------------------------------- */
/* y 272 on the reference canvas */
.tiles-area{position:absolute;left:0;right:0;top:calc(var(--panel)*0.56667);display:flex;justify-content:center}
.tiles{
  display:grid;
  grid-template-columns:repeat(3, calc(var(--panel)*0.21875));   /* 105px */
  column-gap:calc(var(--panel)*0.02708);                          /* 13px */
  row-gap:calc(var(--panel)*0.025);                               /* 12px */
}
.tile{
  position:relative;
  width:calc(var(--panel)*0.21875);height:calc(var(--panel)*0.225);   /* 105 x 108 */
  border:1px solid rgba(132,174,229,0.86);
  border-radius:calc(var(--panel)*0.01667);                       /* 8px */
  background:rgba(3,15,37,0.52);
  color:#ffffff;font:inherit;cursor:pointer;overflow:hidden;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  transition:border-color 150ms ease, background 150ms ease;
}
.tile:hover{border-color:rgba(57,153,255,0.95);background:rgba(6,26,60,0.62)}
.tile:active{background:rgba(8,32,72,0.7)}
.tile:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.tile .ic{
  position:absolute;left:calc(var(--panel)*0.05417);top:calc(var(--panel)*0.02708);
  width:calc(var(--panel)*0.1125);height:calc(var(--panel)*0.1125);   /* 54px at +26,+13 */
  display:flex;align-items:center;justify-content:center;color:#3b98ff;
}
.tile .ic svg{width:100%!important;height:100%!important;display:block}
.tile .cap{
  position:absolute;left:0;right:0;top:calc(var(--panel)*0.15833);    /* +76 */
  display:flex;align-items:flex-start;justify-content:center;text-align:center;
  padding:0 calc(var(--panel)*0.008);
  font-size:calc(var(--panel)*0.025);                                  /* 12px */
  line-height:1.12;letter-spacing:0.01em;color:#ffffff;
}

/* on home the footer is not in flow either — it sits on its reference row, y 684 */
.home-stage .footline{position:absolute;left:0;right:0;top:calc(var(--panel)*1.425);padding:0;margin:0}

.app.at-home .hdr{display:none}

/* 6b. Contacts cards ----------------------------------------------------------
   Measured off the client's mockup (BF8D…, 2.626px per CSS px — see _ref). */
/* The title used to be squashed with transform:scaleX(0.83). A geometric squeeze thins
   the vertical strokes and leaves the horizontals at full weight, which is exactly what
   made it look wrong — the owner called it "weird" and "under an angle" and he was right.
   Archivo carries a real width axis, so it is condensed as a typeface instead. */
.ctitle{
  margin:12px 0 5px;text-align:center;
  font-family:Archivo,Barlow,Helvetica,sans-serif;
  font-variation-settings:'wdth' 80;
  font-size:40px;font-weight:700;letter-spacing:0.012em;color:#f6f8fc;line-height:1;
  text-shadow:0 2px 10px rgba(0,0,0,0.45);
}
.ctitle-rule{
  width:29px;height:2px;margin:8px auto 15px;border-radius:1px;
  background:rgba(160,180,215,0.55);
}
.clist{display:flex;flex-direction:column;gap:8px}
.ccard{
  display:flex;align-items:center;gap:min(9px, calc(var(--panel) * 0.02308));width:100%;
  min-height:61px;padding:6px 6px 6px 7px;
  background:linear-gradient(180deg,#041b39 0%,#03142d 100%);
  border:1px solid #243551;border-radius:12px;
  color:var(--ink);font:inherit;text-align:left;cursor:pointer;
  -webkit-tap-highlight-color:transparent;text-decoration:none;
  transition:border-color 150ms ease, background 150ms ease;
}
.ccard:hover{border-color:rgba(76,140,255,0.85);background:linear-gradient(180deg,#07224a 0%,#041634 100%)}
.ccard:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* measured on the mockup: the frame is 44.9 x 41.9 css, and every glyph sits inside it
   with room to spare — nothing is allowed to reach the border */
.cicon{
  flex:0 0 auto;width:min(40px, calc(var(--panel) * 0.10256));height:min(38px, calc(var(--panel) * 0.09744));border-radius:8px;
  display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid rgba(70,130,210,0.17);
}
.cicon svg{display:block;width:30px;height:30px;filter:drop-shadow(0 1px 4px rgba(0,0,0,0.45))}
.cicon img{display:block;width:auto;height:auto;max-width:88%;max-height:88%}
.cval-ic img{display:block;width:31px;height:auto}
/* the label column gives up space on a narrow phone rather than pushing the value
   out of the card — 320px devices overflowed every row before this */
/* 107px puts the divider at 194 css, where the mockup has it — the value column was
   50px narrower than his and the address had nowhere to go */
/* One column split for every row now — the address does not get its own. 41% is what
   the longest label needs at the solved size while still leaving the longest value a
   real gutter. */
.cmain{flex:0 0 auto;width:37%;min-width:0;align-self:stretch;display:flex;flex-direction:column;gap:6px;padding-top:3px;
  justify-content:center;padding-right:8px;position:relative}
/* the mockup divides the card with a short centred rule, about half its height, not a
   full-height edge */
.cmain::after{content:"";position:absolute;right:0;top:50%;transform:translateY(-50%);
  width:1px;height:29px;background:rgba(70,110,170,0.42)}
/* SOLVED, not chosen. 'OFFICE & MAILING ADDRESS' is the longest label on the screen and
   has to hold one line in the same column as 'PHONE'. Condensing EVERY label to the
   same width axis is what makes that possible without the address looking different
   from its neighbours — which is the whole point of the change. */
.clabel{
  font-family:Archivo,'Archivo FB Label',Barlow,Helvetica,sans-serif;
  /* the axis is real: taking this out puts the address 10px past its divider */
  font-variation-settings:'wdth' 68;
  /* the third term only bites below ~360px, where OFFICE & MAILING ADDRESS would
     otherwise come within 2px of the divider */
  font-size:min(8.2px, calc(var(--panel) * 0.02103), calc(var(--panel) * 0.03955 - 6.432px));
  font-weight:700;letter-spacing:0.012em;color:#f6f6f9;line-height:1.15;white-space:nowrap;
}
/* matched to the mockup by ink: 48.8 x 8.8 css for 'Tap to save' */
.chint{font-family:Archivo,'Archivo FB Hint',Barlow,Helvetica,sans-serif;font-variation-settings:'wdth' 82;
  font-size:min(8.6px, calc(var(--panel) * 0.02205));color:#b9b5c9;line-height:1.2;white-space:nowrap}
/* the address line is the widest value here and used to sit 1px off the divider —
   the column keeps real clearance on both sides now */
.cval{flex:1 1 auto;min-width:0;display:flex;align-items:center;justify-content:center;padding:0 5px}
.cval-text{
  font-family:Archivo,'Archivo FB Value',Barlow,Helvetica,sans-serif;font-variation-settings:'wdth' 70;
  font-size:min(11.4px, calc(var(--panel) * 0.02924));font-weight:600;color:#1587fb;line-height:1.35;text-align:center;
  white-space:nowrap;
}
.cval-ic{display:flex}
/* Nothing is special-cased by row any more: every label, hint and value on this screen
   is the same size. The address row keeps one thing of its own — a looser line height,
   because it is the only value that runs to two lines. */
.ccard.is-addr .cval-text{line-height:1.5}

/* The sign-in control: contacts only, under the footer line, deliberately quiet. */
/* a column now, and set well clear of the ACROSS CANADA line above it — at 2px the
   credit read as part of the footer rather than as a separate note underneath it */
.adminline{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:22px 0 calc(env(safe-area-inset-bottom) + 8px)}
.adminlink{
  background:none;border:0;padding:4px 10px;font:inherit;
  /* smaller again on 2026-08-29 — it is a technicality, not a feature */
  font-size:7.5px;font-weight:500;letter-spacing:0.11em;text-transform:uppercase;
  color:rgba(116,146,188,0.42);cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.adminlink:hover{color:rgba(160,195,240,0.85)}

/* The credit under the sign-in link. Set below even the Login button, which is already
   the quietest thing on the site — it is a signature, not a piece of the page. */
.credit{
  margin:0 0 3px;display:flex;flex-direction:column;gap:1px;
  /* sentence case, not capitals: he asked for it read rather than shouted, and
     lower case needs almost no tracking to stay legible at this size */
  font-size:7.5px;line-height:1.55;letter-spacing:0.012em;
  color:rgba(134,167,213,0.5);text-align:center;
}
/* One colour for all of it, his instruction of 2026-08-31: neither name is picked out
   by weight or by colour. The link only lifts under a cursor, so it stays findable. */
.credit a{font-weight:inherit;color:inherit;text-decoration:none}
.credit a:hover{color:rgba(170,205,247,0.8)}

/* the footline pattern reused inside a scrolling page */

/* 6c. Scroll indicator --------------------------------------------------------
   Rebuilt to the owner's screenshot of 2026-08-29: a slim bar with rounded ends that
   narrows gently from head to foot, deep blue at the top and pale at the bottom, with a
   small white ball riding it. Sizes come from that image (738 px wide): the bar sits
   6.5% of the panel in from the right edge, and assets/js/app.js shapes the path.
   The native scrollbar is hidden. */
.scroll{scrollbar-width:none}
.scroll::-webkit-scrollbar{display:none}
.sb{position:absolute;right:calc(var(--panel)*0.065 - 15px);width:30px;z-index:60;opacity:0;pointer-events:none;transition:opacity 320ms ease}
/* only while the page is actually moving — assets/js/app.js adds sb-live on scroll
   and drops it 1.4s after the last scroll event */
.app.has-scroll.sb-live .sb{opacity:1}
.sb svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;filter:drop-shadow(0 0 5px rgba(40,110,255,0.5))}
/* Drawn small, grabbed big. The element itself is a 30px invisible target — the size
   the owner asked to keep — and the white dot is its ::after, sized by --ball from
   assets/js/app.js to the 3.93%-of-panel the screenshot has. */
.sb-ball{
  position:absolute;left:50%;top:0;width:30px;height:30px;margin-left:-15px;
  background:none;border:0;
  /* An invisible 30px target must not swallow taps: it sits in the top-right corner
     at scroll 0, right where the Francais button is. It only accepts a finger while the
     bar is actually on screen. */
  pointer-events:none;cursor:grab;touch-action:none;
}
.app.has-scroll.sb-live .sb-ball{pointer-events:auto}
.sb-ball::after{
  content:"";position:absolute;left:50%;top:50%;
  width:var(--ball,16px);height:var(--ball,16px);margin:calc(var(--ball,16px)/-2) 0 0 calc(var(--ball,16px)/-2);
  border-radius:50%;
  background:radial-gradient(circle at 34% 28%, #ffffff 0%, #f4f2ec 52%, #ddd9cf 100%);
  box-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 10px rgba(150,200,255,0.5);
}
.sb-ball:active{cursor:grabbing}

/* 7. Inner screens --------------------------------------------------------- */
.scroll{
  flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  /* 20 left / 41 right, off the mockup: the content ends at 349css and the scroll
     indicator owns the lane to its right instead of overlapping the cards */
  overscroll-behavior:contain;padding:0 var(--scroll-r) 0 var(--scroll-l);
  /* a column so the footline can be pushed to the bottom edge on a short page,
     while a long page simply lets it follow the content */
  display:flex;flex-direction:column;
}
.scroll > *{flex:0 0 auto}
.stitle{font-size:clamp(21px,6vw,27px);font-weight:700;letter-spacing:-0.01em;margin:2px 0 6px;text-align:center}
.slead{margin:0 0 18px;color:var(--sub);font-size:clamp(14px,4vw,16px);line-height:1.55}
.card{
  background:var(--card);border:1px solid var(--line);border-radius:16px;padding:2px 16px;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.row{
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;padding:14px 0;
  border-bottom:1px solid var(--line);font-size:clamp(14px,4vw,16px);
}
.row:last-child{border-bottom:0}
.rkey{color:var(--sub);flex:1 1 auto;min-width:0;text-align:left}
.rval{font-weight:600;text-align:right;color:var(--ink)}
.rowbtn{
  width:100%;background:none;border:0;font:inherit;cursor:pointer;
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;padding:14px 0;
  border-bottom:1px solid var(--line);font-size:clamp(14px,4vw,16px);color:var(--ink);
  text-align:left;-webkit-tap-highlight-color:transparent;
}
.rowbtn:last-child{border-bottom:0}
.rowbtn:focus-visible,.back:focus-visible,.langbtn:focus-visible,a:focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:6px;
}
.rview{font-weight:600;color:var(--accent);flex-shrink:0}
.dochead{
  font-size:12px;font-weight:600;color:var(--sub);text-transform:uppercase;
  letter-spacing:0.08em;margin:22px 0 9px;
}

.biglist{display:flex;flex-direction:column;gap:10px}
.biglist.gap-top{margin-top:16px}
.biglist.gap-top-lg{margin-top:22px}
.biglist.gap-top-xl{margin-top:24px}
.bigbtn{
  display:flex;align-items:center;gap:14px;background:var(--card);border:1px solid var(--line);
  border-radius:16px;padding:14px 16px;min-height:62px;color:var(--ink);cursor:pointer;font:inherit;
  text-align:left;width:100%;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:border-color 160ms ease, background 160ms ease;
}
.bigbtn:hover{border-color:rgba(47,123,255,0.75);background:rgba(16,38,74,0.6)}
.ticon{
  width:42px;height:42px;border-radius:12px;background:rgba(47,123,255,0.16);
  border:1px solid rgba(47,123,255,0.35);display:flex;align-items:center;justify-content:center;
  color:var(--accent);flex-shrink:0;
}
.btext{display:flex;flex-direction:column;gap:2px;min-width:0}
.blabel{font-size:clamp(15px,4.2vw,17px);font-weight:600}
.bsub{font-size:clamp(12.5px,3.5vw,14px);color:var(--sub);overflow-wrap:anywhere}

.plist{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:13px}
.plist li{display:grid;grid-template-columns:20px 1fr;gap:11px;align-items:start;font-size:clamp(14px,4vw,16px);line-height:1.5}
.plist svg{margin-top:3px;color:var(--accent)}
.plist b{display:block;font-weight:600;margin-bottom:2px}
.plist span{color:var(--sub)}

.empty{
  border:1px dashed var(--line);border-radius:16px;padding:24px 20px;text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:11px;background:rgba(8,20,40,0.3);
}
.empty p{margin:0;color:var(--sub);font-size:clamp(14px,4vw,16px);line-height:1.55}
.note{font-size:clamp(12.5px,3.5vw,13.5px);color:var(--sub);margin:12px 2px 0;line-height:1.5}
.foot{padding-top:22px;text-align:center;font-size:12.5px;color:var(--sub)}

/* 7a. About us -----------------------------------------------------------------
   Built to the client's nine screenshots (see _ref). Cards are the sampled
   #16445e teal-navy with white text; photos fill the card width; the
   Mont-Saint-Hilaire block is a serif "poster" with a thin blue frame, and the
   outro reuses the home-tile look for its two links. */
/* the reference document: the page itself is the #103650 blue, cards are #16445e on
   it, and every corner is near-square (radius 4 measured off IMG_2251 — 10 device px
   at 3x). Do not round anything here again. */

/* Plain text on the page background — his instruction of 2026-08-29. No card fills,
   no card padding, one size and one weight throughout, and the space between two
   paragraphs is the same as the space between two lines inside one. Photographs keep a
   little air of their own, or they butt straight into the sentence above them. */
.abt{
  /* no top margin, and the first photograph has no top margin either: the scroll
     indicator is anchored to this container, and any air above the picture showed up as
     the bar starting a few pixels too high — only on this screen */
  display:flex;flex-direction:column;gap:0;margin-top:0;
  /* 1.24, not 1.55: he asked for the leading to come down a fifth on 2026-09-03.
     Every line on this page inherits it, so this one number sets the whole page. */
  font-size:15.5px;line-height:1.24;color:#f2f7fb;font-weight:400;
}
/* Every paragraph on this page: one size, one weight, and NO space between them —
   that is how he wants it read, lines one under another. This rule used to end with
   '.abt-outro p' and I deleted that selector together with the declaration block it
   shared with the four above it, which is what put a gap under every paragraph on the
   page. A grouped selector carries one block: never remove the last name in the list. */
.abt p,
.abt .abt-h,
.abt .abt-cap{
  margin:0;font-size:inherit;line-height:inherit;font-weight:400;
  font-family:inherit;color:inherit;text-align:left;
}
/* Ten pixels, in the two places he named on 2026-09-03: under the line about already
   working in Canada, and under the magnets paragraph. Everywhere else the page runs on,
   and it stays that way unless he names another spot. */
.abt p.abt-gap{margin-bottom:10px}
.abt-card{background:none;border:0;border-radius:0;padding:0;font:inherit;color:inherit}
/* A new story gets air above it, and nothing else does. Ten pixels, the same as the two
   paragraph gaps he named — one number for every deliberate space on this page. */
.abt .abt-break{margin-top:10px}
.abt-center{text-align:center}

/* photographs: the only things on this page that still hold space around themselves */
/* they open in the lightbox like the gallery does, so they say so under the cursor */
.abt-photo{display:block;width:100%;height:auto;border-radius:0;cursor:zoom-in}
.abt-card .abt-photo,
.abt-shots .abt-photo,
.abt-poster .abt-photo{margin:14px 0}
.abt > :first-child .abt-photo:first-of-type,
.abt > :first-child picture:first-child .abt-photo{margin-top:0}

/* The thermal spa keeps the shape it always had, on his instruction of 2026-09-02:
   one wide photograph, then a pair side by side, then one wide again. It is the only
   group on the page that is NOT two a row, and that is deliberate. */
.abt-shots{display:flex;flex-direction:column;gap:12px}
/* the column ratio used to be the two old crops' widths, and the images were cropped to
   fill; both originals are the same shape now and neither is cropped */
.abt-duo{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start;margin:14px 0}
.abt-duo img{display:block;width:100%;height:auto;object-fit:contain}
.abt-duo .abt-photo{margin:0}

/* The four Winnipeg photos: one per row, each at full width. They were two-up and he
   asked for them big — and nothing is cropped, so each keeps its own height. */
/* Two a row, his instruction of 2026-09-02 — the same as the gallery on Our Work.
   An odd number simply leaves the last one alone in its row. */
.abt-stack{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin:14px 0;align-items:start}
.abt-stack img{display:block;width:100%;height:auto}
.abt-stack .abt-photo{margin:0}

/* Mont-Saint-Hilaire: the frame, the fill and the serif are gone with everything else */
.abt-poster{
  border:0;border-radius:0;background:none;padding:0;
  display:flex;flex-direction:column;gap:0;
  font:inherit;color:inherit;
}

/* 8. Gallery and administration -------------------------------------------
   The photo grid is public; everything with .abtn on it is drawn only when PHP
   knows the visitor is signed in. See inc/gallery.php and admin.php.
   -------------------------------------------------------------------------- */
.gallery{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin:4px 0 0}

/* --- Contacts: the mailbox and the parking space ------------------------------
   Two photographs side by side under the cards, his layout of 2026-09-06. They keep
   their own shapes — one upright, one wide — and sit against the top of the row, the
   way the About page pairs its photographs. */
.cshots{
  display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:start;
  margin:16px 0 0;
}
.cshot{margin:0}
.cshot img{
  display:block;width:100%;height:auto;border-radius:12px;
  border:1px solid var(--line);cursor:zoom-in;
  -webkit-tap-highlight-color:transparent;
  transition:border-color 160ms ease, transform 160ms ease;
}
.cshot img:hover{border-color:rgba(47,123,255,0.75);transform:translateY(-2px)}
/* his words under each, at the site's note size and the site's grey */
.cshot-cap{
  margin:6px 2px 0;text-align:center;
  font-size:12px;line-height:1.35;color:var(--sub);
}

/* --- Emailing photographs -----------------------------------------------------
   Any picture on the site can be sent to an address. assets/js/send.js hangs the control
   on whatever holds the image — a gallery button, a certificate tile, or a wrapper it
   makes for a bare <img> — so these rules have to work on all three. */
.sendable{position:relative}
.sendwrap{display:block;position:relative;line-height:0}
.sendwrap img{width:100%;height:auto;display:block}

.sendtick, .sendone{
  position:absolute;z-index:3;
  display:flex;align-items:center;justify-content:center;
  padding:0;cursor:pointer;color:#dce9fb;
  border:1px solid rgba(140,180,235,0.5);
  background:rgba(6,17,36,0.72);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  -webkit-tap-highlight-color:transparent;
  transition:background 140ms ease, border-color 140ms ease, color 140ms ease, transform 140ms ease;
}
/* a 30px target in the corner: big enough for a thumb, small enough not to hide the photo */
.sendtick{top:7px;right:7px;width:30px;height:30px;border-radius:50%}
.sendtick svg{opacity:0.55}
.sendtick:hover{border-color:rgba(47,123,255,0.9)}
.sendtick[aria-pressed="true"]{background:var(--accent);border-color:#a8c9ff;color:#fff}
.sendtick[aria-pressed="true"] svg{opacity:1}
.sendable.is-picked{outline:2px solid var(--accent);outline-offset:2px}

/* one picture on the screen: an envelope rather than a tick, because there is nothing
   to collect — pressing it sends that photograph */
.sendone{top:7px;right:7px;height:30px;border-radius:15px;gap:0;width:34px}
.sendone:hover{background:var(--accent);border-color:#a8c9ff;color:#fff}
.sendtick:focus-visible, .sendone:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* the bar that counts what is ticked; it lives on document.body, so it is measured
   against the panel the site is drawn in rather than the window */
.sendbar{
  position:fixed;z-index:115;bottom:14px;
  left:50%;transform:translateX(-50%);
  width:min(calc(100vw - 24px), calc(var(--panel-raw) - 28px));
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 10px 9px 14px;border-radius:14px;
  border:1px solid rgba(47,123,255,0.5);background:rgba(10,26,52,0.94);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  box-shadow:0 10px 30px rgba(0,0,0,0.45);
}
.sendbar-n{font-size:13px;font-weight:600;color:#dce9fb;letter-spacing:0.01em}
.sendbar-do{display:flex;gap:6px;flex:0 0 auto}

/* the same envelope over the open photograph, beside the close button so it never
   collides with the caption at the foot */
.lbtop-r{display:flex;align-items:center;gap:8px}
.lbsend{
  width:44px;height:44px;border-radius:22px;border:0;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.14);color:#fff;
  -webkit-tap-highlight-color:transparent;
  transition:background 140ms ease;
}
.lbsend:hover{background:var(--accent)}
.lbsend:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* --- Work details: the six categories -----------------------------------------
   His layout of 2026-09-04 — three across, two down, square outlined tiles with the
   name centred in them and nothing else. The grid is narrower than the column, the
   way he drew it, so the tiles stay square instead of stretching on a wide phone. */
.catgrid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:12px;
  max-width:322px;margin:0 auto;
}
.cat{
  position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;min-width:0;
  aspect-ratio:1 / 1.06;padding:8px 6px;
  font:inherit;color:#eaf2ff;text-align:center;cursor:pointer;
  border:1px solid var(--line);border-radius:12px;background:rgba(8,20,40,0.42);
  -webkit-tap-highlight-color:transparent;
  transition:border-color 160ms ease, transform 160ms ease, background 160ms ease;
}
.cat:hover{border-color:rgba(47,123,255,0.75);background:rgba(18,44,86,0.6);transform:translateY(-2px)}
.cat:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.cat-label{font-size:11.5px;font-weight:700;letter-spacing:0.04em;line-height:1.25}
/* how many photographs are in there, small and out of the way */
.cat-count{
  position:absolute;top:6px;right:8px;
  font-size:10px;font-weight:600;color:var(--sub);letter-spacing:0.02em;
}
/* a nought is still worth reading — quieter than a count, but there */
.cat-count.is-none{color:#5b7091}

/* a note under the tiles rather than over them needs its air on the other side */
.catgrid + .doc-note{margin-top:13px}

/* Materials: his copy under the three tiles, at the same size as the Estimate lead so
   the two written screens read alike. The second block is separated by space alone —
   photographs of the sample books go in there later. */
.mat-lead{margin:14px 0 0;font-size:14px;font-weight:400;line-height:1.5;color:#dce7f6}
.mat-block{margin-top:18px}
.mat-block .mat-lead{margin-top:0}

/* --- A manufacturer's own page inside Materials -------------------------------
   The video is a still of ours that opens YouTube in a new tab, not an embed: an embed
   would load Google's player for every visitor who never asked to watch anything. */
.matvideo{
  display:block;margin:16px 0 0;text-decoration:none;color:inherit;
  -webkit-tap-highlight-color:transparent;
}
.matvideo-shot{
  position:relative;display:block;line-height:0;
  border:1px solid var(--line);border-radius:12px;overflow:hidden;
  transition:border-color 160ms ease, transform 160ms ease;
}
.matvideo-shot img{display:block;width:100%;height:auto}
.matvideo:hover .matvideo-shot{border-color:rgba(47,123,255,0.75);transform:translateY(-2px)}
.matvideo-play{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  display:flex;align-items:center;justify-content:center;
  width:52px;height:52px;border-radius:50%;
  background:rgba(6,17,36,0.72);border:1px solid rgba(180,210,255,0.6);color:#fff;
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
}
.matvideo:hover .matvideo-play{background:var(--accent);border-color:#a8c9ff}
.matvideo-cap{
  display:block;margin-top:8px;font-size:12.5px;line-height:1.4;color:var(--sub);
}
.matvideo-cap b{display:block;font-weight:700;color:#dce7f6;margin-bottom:1px}

/* The manufacturer's notice at the head of their own page, and the working hours at the
   foot of Contacts: both are small grey lines that frame what is around them, not content
   of their own. */
.mat-notice{margin:0 0 14px}
.chours{margin-top:14px}

/* "under construction" on a manufacturer's tile: small and grey, so the tile still reads
   as its name first and tells you the page is empty before you open it. */
.cat-soon{
  display:block;margin:0;font-size:7.5px;font-weight:400;line-height:1.2;
  letter-spacing:0.02em;color:var(--sub);
}

.mat-sub{
  margin:18px 0 6px;font-size:11.5px;font-weight:700;letter-spacing:0.08em;
  text-transform:uppercase;color:var(--sub);
}
.matlinks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.matlinks a{
  display:block;padding:10px 12px;border-radius:11px;
  border:1px solid var(--line);background:rgba(8,20,40,0.45);
  font-size:13.5px;line-height:1.35;color:#cfe0f8;text-decoration:none;
  transition:border-color 140ms ease, background 140ms ease, color 140ms ease;
}
.matlinks a:hover{border-color:rgba(47,123,255,0.75);background:rgba(18,44,86,0.6);color:#fff}
.matlinks a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.catview .doc-note{margin-top:10px}

/* His photographs of the sample books: two across, every picture keeping its own shape —
   and NO gaps between them (2026-09-06). A grid cannot do that with mixed shapes: rows
   are as tall as their tallest cell, so an upright photograph beside a wide one leaves a
   hole under the wide one. Columns can: each picture starts where the one above it ended,
   so the two columns fill themselves and simply end at different heights. */
.matgrid{
  column-count:2;column-gap:10px;margin:4px 0 0;
}
.matgrid picture{
  display:block;line-height:0;
  margin:0 0 10px;
  -webkit-column-break-inside:avoid;break-inside:avoid;
}
.matshot{
  display:block;width:100%;height:auto;border-radius:12px;
  border:1px solid var(--line);cursor:zoom-in;
  -webkit-tap-highlight-color:transparent;
  transition:border-color 160ms ease, transform 160ms ease;
}
.matshot:hover{border-color:rgba(47,123,255,0.75);transform:translateY(-2px)}

/* SOPREMA's photographs: two across in ROWS, so a range reads left to right in the order
   of its colours, each picture with the colour name SOPREMA gave it underneath. The tile
   is a fixed 4:3 so the rows line up; the lightbox shows the whole picture. */
.matrows{display:grid;grid-template-columns:1fr 1fr;gap:12px 10px;margin:0 0 4px}
.matrows .matfig{margin:0;min-width:0}
.matrows .matfig picture{display:block;line-height:0}
.matrows .matshot{aspect-ratio:4/3;object-fit:cover}
.matcap{display:block;margin-top:4px;font-size:11.5px;line-height:1.3;color:var(--sub)}
.mat-range{margin:16px 0 8px;font-size:14px;font-weight:700;letter-spacing:0.02em;color:#dce7f6}
/* a plain membrane's sample is its colour: three squares, named */
.matchips{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:0 0 10px}
.matchip{display:block;text-align:center;font-size:11.5px;line-height:1.3;color:var(--sub)}
.matchip img{
  display:block;width:100%;height:auto;aspect-ratio:1;object-fit:cover;
  border-radius:10px;border:1px solid var(--line);margin:0 0 4px;
}
.matdoc-size{display:block;margin-top:2px;font-size:11.5px;color:var(--sub)}

/* the open category: the way back, and then the grid. The name is not here — it is the
   page title at the top while the category is open. */
.cathead{display:flex;align-items:center;gap:10px;margin:0 0 12px}
/* the screen's own icon and the whole phrase, so the way back is unmistakable */
.catback{flex:0 1 auto;display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  min-width:0;overflow:hidden}
.catback svg{flex:0 0 auto;color:var(--accent)}
.catback span{overflow:hidden;text-overflow:ellipsis}
.cat-title{
  margin:0;font-size:14px;font-weight:700;letter-spacing:0.06em;color:#eaf2ff;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* auto rows for the image and caption, then the tools pinned to the bottom, so a long
   caption in one cell does not shove its neighbours out of line */
.shot{margin:0;position:relative;display:grid;grid-template-rows:auto 1fr auto;gap:6px}
.shot-open{
  display:block;padding:0;border:1px solid var(--line);border-radius:14px;overflow:hidden;
  background:rgba(6,17,36,0.5);cursor:zoom-in;line-height:0;
  -webkit-tap-highlight-color:transparent;
  transition:border-color 160ms ease, transform 160ms ease;
}
.shot-open:hover{border-color:rgba(47,123,255,0.75);transform:translateY(-2px)}
.shot-open:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.shot-open img{width:100%;height:100%;aspect-ratio:4/3;object-fit:cover;display:block}
.shot-cap{
  font-size:clamp(12px,3.3vw,13px);color:var(--sub);line-height:1.35;
  padding:0 2px;overflow-wrap:anywhere;
}
/* four controls have to fit one grid column on a phone, so they are glyph-only and
   share the width evenly */
.shot-tools{display:flex;align-self:end;gap:4px;padding:0 1px 2px}
.shot-tools .abtn{flex:1 1 0;min-width:0;height:34px;padding:0 4px;font-size:14px}
/* the position, which is also the control that changes it — the widest of the three,
   because it is the one that carries information */
.abtn-num{
  flex:1.4 1 0 !important;font-weight:700;font-variant-numeric:tabular-nums;
  color:#cfe0f8;border-color:rgba(90,150,235,0.5);background:rgba(9,32,70,0.75);
}
.abtn-num:hover:not(:disabled){color:#fff;border-color:rgba(130,190,255,0.9)}

.adminbar{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;
  margin:0 0 14px;padding:10px 12px;
  border:1px solid rgba(47,123,255,0.42);border-radius:14px;
  background:rgba(16,40,80,0.5);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.adminbar-who{font-size:12.5px;color:#bfd4f2;font-weight:600;letter-spacing:0.02em}
.adminbar-actions{display:flex;flex-wrap:wrap;gap:6px}
.adminbar-note{
  margin:-6px 0 14px;padding:9px 12px;border-radius:12px;font-size:13px;line-height:1.4;
  background:rgba(16,40,80,0.5);border:1px solid var(--line);color:#cfe0f8;
}
.adminbar-note.is-bad{border-color:rgba(255,120,120,0.55);color:#ffd6d6}
.adminbar-note.is-good{border-color:rgba(90,220,150,0.5);color:#c9f7de}

.abtn{
  font:inherit;font-size:12.5px;font-weight:600;line-height:1;
  padding:8px 11px;min-height:34px;border-radius:9px;cursor:pointer;
  border:1px solid var(--line);background:rgba(8,20,40,0.7);color:#e6efff;
  -webkit-tap-highlight-color:transparent;
  transition:border-color 140ms ease, background 140ms ease, opacity 140ms ease;
}
.abtn:hover:not(:disabled){border-color:rgba(47,123,255,0.8);background:rgba(18,44,86,0.8)}
.abtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.abtn:disabled{opacity:0.4;cursor:default}
.abtn-go{background:var(--accent);border-color:#82b1ff;color:#fff}
.abtn-go:hover:not(:disabled){background:#1e6cf0;border-color:#a8c9ff}
.abtn-danger:hover:not(:disabled){border-color:rgba(255,110,110,0.8);background:rgba(86,20,20,0.7);color:#ffd9d9}
.abtn-icon{padding:8px 10px;min-width:34px}
.abtn-wide{width:100%;padding:12px;font-size:14px;min-height:44px;margin-top:4px}


/* the dialog: sign in, caption, password */
.sheet{
  position:fixed;inset:0;z-index:120;display:flex;align-items:center;justify-content:center;
  padding:16px;background:rgba(2,6,14,0.72);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
}
/* The invoice form is taller than a phone. The card caps itself against the visible
   viewport and scrolls its own body, so the title and the close button never leave
   the screen and nothing is cut off at either end. dvh first, vh for the browsers
   that predate it. */
.sheet-card{
  position:relative;width:100%;max-width:340px;
  max-height:calc(100vh - 32px);
  max-height:calc(100dvh - 32px);
  display:flex;flex-direction:column;
  padding:20px 18px 18px;border-radius:18px;
  border:1px solid rgba(150,190,245,0.28);
  background:linear-gradient(180deg,#0d2043 0%,#081428 100%);
  box-shadow:0 30px 70px -20px rgba(0,0,0,0.8);
}
.sheet-close{
  position:absolute;top:8px;right:8px;width:34px;height:34px;border-radius:17px;
  border:0;background:rgba(255,255,255,0.1);color:#fff;font-size:15px;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.sheet-title{flex:0 0 auto;margin:0 34px 14px 0;font-size:17px;font-weight:700;letter-spacing:-0.01em}
.sheet-body{
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  display:flex;flex-direction:column;gap:12px;
  /* Room for the focus ring on EVERY side. With no left padding the scroll container
     cut the outline off the left of each field — visible the moment one was tapped. */
  padding:3px;
  margin:0 -3px;
}
.field{display:flex;flex-direction:column;gap:5px}
.field-label{font-size:12px;font-weight:600;color:var(--sub);letter-spacing:0.03em;text-transform:uppercase}
.field-input{
  font:inherit;font-size:15px;padding:11px 12px;min-height:44px;
  border-radius:10px;border:1px solid var(--line);
  background:rgba(3,10,22,0.75);color:var(--ink);
}
select.field-input{-webkit-appearance:none;appearance:none;width:100%;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 8%27><path d=%27M1 1.5 6 6.5 11 1.5%27 fill=%27none%27 stroke=%27%2394b0d4%27 stroke-width=%271.6%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27/></svg>");
  background-repeat:no-repeat;background-position:right 12px center;background-size:12px 8px;padding-right:34px}
select.field-input option{background:#0a1526;color:var(--ink)}
.field-input::placeholder{color:#5d7391}
.field-input:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}
.sheet-msg{flex:0 0 auto;margin:12px 0 0;font-size:13px;line-height:1.4;color:#cfe0f8}
.sheet-msg.is-bad{color:#ffb4b4}
.sheet-msg.is-good{color:#a9f0c9}

/* 9. Lightbox -------------------------------------------------------------- */
.lbx-wrap{
  position:fixed;inset:0;background:rgba(2,6,12,.97);z-index:100;
  display:flex;align-items:center;justify-content:center;touch-action:pan-y;
}
.lbx-wrap img{
  max-width:100vw;max-height:calc(100dvh - 120px);object-fit:contain;
  user-select:none;-webkit-user-drag:none;transition:opacity .18s ease;
}
.lbtop{
  position:absolute;top:0;left:0;right:0;display:flex;justify-content:space-between;align-items:center;
  padding:calc(env(safe-area-inset-top) + 12px) 16px 12px;color:#fff;
}
.lbcount{font-size:14px;font-weight:600;color:rgba(255,255,255,.75);font-variant-numeric:tabular-nums}
.lbcap{
  position:absolute;bottom:calc(env(safe-area-inset-bottom) + 14px);left:0;right:0;
  text-align:center;color:rgba(255,255,255,.75);font-size:13px;padding:0 24px;
}
.lbclose{
  width:44px;height:44px;border-radius:22px;border:0;background:rgba(255,255,255,.14);color:#fff;
  font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;
}
.lbnav{
  position:absolute;top:50%;transform:translateY(-50%);width:48px;height:64px;border:0;background:none;
  color:rgba(255,255,255,.65);font-size:38px;cursor:pointer;padding:0;line-height:1;
}
.lbprev{left:4px}
.lbnext{right:4px}

@media(pointer:coarse){.lbnav{display:none}}
@media(prefers-reduced-motion:reduce){*{transition:none!important}}

/* 10. Desktop ---------------------------------------------------------------
   On a wide screen the app stops being a floating strip and becomes a framed
   panel over the photo: same proportions, same behaviour, just presented like
   something that was meant to be there. --u is re-based on the panel width so
   every calc() above keeps its phone proportions.
   -------------------------------------------------------------------------- */
@media (min-width:840px) and (min-height:560px){
  /* Two photographs a row here as well. The panel is the same width on a computer as
     on a phone, so there was never a reason for the two to differ, and he asked for
     two everywhere on 2026-09-01. */
  :root{
    --screen-h:min(920px, calc(100dvh - 56px));
    --screen-w:clamp(340px, calc(var(--screen-h) / 2.04), 440px);
    --screen-radius:28px;
    --u:var(--screen-w);
    --hw:var(--screen-w);
    --pad-t:14px;
    --pad-r:18px;
    --pad-b:16px;
    --pad-l:18px;
  }

  /* On a computer the photograph does NOT fill the window. It is a phone photograph —
     a 943x1668 frame — and across 1440px it is a blue column and some palm fronds with
     the app floating over it. Instead the whole background layer becomes the panel:
     same box as .app, same corners, and the photo, the strips and the vignette all
     work inside it exactly as they do on a phone. */
  .bg{
    left:50%;top:50%;right:auto;bottom:auto;
    width:var(--screen-w);height:var(--screen-h);
    transform:translate(-50%, -50%);
    border-radius:var(--screen-radius);overflow:hidden;
  }
  .vign{
    left:50%;top:50%;right:auto;bottom:auto;
    width:var(--screen-w);height:var(--screen-h);
    transform:translate(-50%, -50%);
    border-radius:var(--screen-radius);
  }
  /* The window around the panel is pool water — his own photograph, 2026-09-02 — under a
     dark wash. The wash is what keeps the frame and the Canada outline readable over it;
     the water alone is busy enough to swallow a hairline. */
  body{
    background-color:#03080f;
    background-image:
      linear-gradient(180deg, rgba(2,7,15,0.52) 0%, rgba(3,10,20,0.30) 45%, rgba(2,6,13,0.58) 100%),
      url('/img/desk-bg.jpg');
    background-image:
      linear-gradient(180deg, rgba(2,7,15,0.52) 0%, rgba(3,10,20,0.30) 45%, rgba(2,6,13,0.58) 100%),
      image-set(url('/img/desk-bg.webp') type('image/webp'), url('/img/desk-bg.jpg') type('image/jpeg'));
    background-size:cover, cover;
    background-position:center, center;
    background-repeat:no-repeat, no-repeat;
    background-attachment:fixed, fixed;
  }

  /* The panel is the whole app — header included — so it is .app that gets the frame,
     not the individual screens. */
  .app{
    position:fixed;inset:auto;left:50%;top:50%;transform:translate(-50%,-50%);
    width:var(--screen-w);height:var(--screen-h);max-width:none;margin:0;
    border-radius:var(--screen-radius);overflow:hidden;
    box-shadow:0 40px 90px -20px rgba(0,0,0,0.75), 0 0 0 1px rgba(150,190,245,0.16),
               inset 0 1px 0 rgba(255,255,255,0.06);
    background:linear-gradient(180deg, rgba(9,22,44,0.42) 0%, rgba(4,11,24,0.52) 100%);
    -webkit-backdrop-filter:blur(3px) saturate(1.15);
    backdrop-filter:blur(3px) saturate(1.15);
  }
  .hdr{padding-top:0}
  .screens{flex:1 1 auto;min-height:0}
  .screen{flex:1 1 auto;min-height:0;box-shadow:none;background:none;backdrop-filter:none}

  /* A quiet line at the foot of the frame, computer only: the frame is the design, and
     someone arriving on a desktop should not read it as something broken. */
  /* On home the panel IS the photograph now, so the glass fill and the blur that used
     to sit over a window-wide picture would only dim and soften it. The frame stays,
     the tint goes. Inner screens keep it: there it separates the panel from the flat
     colour behind it. */
  body.at-home-bg .app{background:none;-webkit-backdrop-filter:none;backdrop-filter:none}

  /* the panel is narrower than a phone in CSS px, so the clamp()-based type
     inside the inner screens needs a fixed size instead of a vw-based one */
  .stitle{font-size:25px}
  .slead,.row,.rowbtn,.plist li,.empty p{font-size:15px}
  .blabel{font-size:16px}
  .bsub{font-size:13px}
  .back{font-size:16px}

  /* No scrollbar styling on purpose. The client's own build styles none — computed
     style on it is scrollbar-width:auto, scrollbar-color:auto, and there is not one
     ::-webkit-scrollbar rule in its CSS (checked with _ref/css-diff.js). A thin blue
     bar was tried here and removed again: matching what he had beats improving it. */

  .lbx-wrap img{max-width:min(1100px,92vw);max-height:calc(100dvh - 150px)}
}

/* Very wide screens: cap how much the photo is scaled so it stays sharp. */


/* --- Standard footline (every screen, home included) -------------------------
   Measured off the approved reference, canvas 480 (_ref/measure-ref-footer.js):
     Quality First  element 112 x 50 at x 313, y 684
     rules          86 wide, x 55..140 and x 340..425, at y 760
     words          x 155..297, then 12px, then the maple leaf 12 x 14 at x 310..321
   The rules are a FIXED length, not "whatever is left in the row". That is what the
   client asked for on 2026-08-29, and it is also why this footer now comes out identical
   on every page instead of following the width of the column it happens to sit in. */
.footline{
  flex:0 0 auto;position:relative;height:auto;min-height:0;
  display:flex;flex-direction:column;align-items:stretch;
  padding:18px 0 calc(env(safe-area-inset-bottom) + 2px);
  margin-top:auto;
}
/* row one exists only to hold the signature at its reference x — 313 of 480 */
.fq{position:relative;height:calc(var(--panel)*0.10417)}          /* 50px */
.quality-img{
  position:absolute;left:calc(var(--panel)*0.65208);top:0;        /* x 313 */
  display:block;width:calc(var(--panel)*0.23333);height:auto;max-width:none;   /* 112px */
  margin:0;
}
.fbar{
  display:flex;align-items:center;justify-content:center;
  margin-top:calc(var(--panel)*0.03333);                          /* 734 -> 750 */
}
.frule{flex:0 0 auto;width:calc(var(--panel)*0.17917);height:1px;background:rgba(47,123,255,0.55)}
.frule-l{margin-right:calc(var(--panel)*0.03125)}                 /* 140 -> 155 */
.frule-r{margin-left:calc(var(--panel)*0.03958)}                  /* 321 -> 340 */
.across{
  display:flex;align-items:center;gap:calc(var(--panel)*0.025);   /* 12px to the leaf */
  font-weight:600;letter-spacing:0.07em;color:#2f80ff;white-space:nowrap;
  font-size:calc(var(--panel)*0.03458);                           /* words 142px wide */
}
/* The leaf was 0.025 (12px at the 480 canvas), straight off the client's mockup — but the
   maple path carries its own margin inside a 512 viewBox, so only about 9px of it was ink
   and it read as a speck beside 16px letters. His call, 2026-09-14: bigger. 0.044 puts the
   ink at roughly the height of the capitals next to it. */
.across svg{flex:0 0 auto;display:block;width:calc(var(--panel)*0.044);height:auto}

/* The footer has to be the same on every page - he asked for that in those words on
   2026-08-29 - so inside a scrolling screen it steps back OUT of the content column's
   asymmetric padding (20 left, 41 right, which exists only to keep the scroll lane clear
   of the cards) and takes the same symmetric inset the home screen uses. Without this the
   rules are 15px shorter here and the whole line sits 10px left of centre. */
.scroll .footline{margin:auto calc(-1 * var(--scroll-r)) 0 calc(-1 * var(--scroll-l))}
/* On HOME the signature sits on the grey ramp in the photograph and the owner wants it
   left alone. On every other screen there is no photograph, and the same position puts
   its ink 21px to the LEFT of the rule beside ACROSS CANADA, which reads as a mistake.
   Here it is shifted so the ink is centred on that rule: its ink runs 320..403 of the
   480 canvas, the rule 340..425, so +21 lands it at 341..424 — inside, both ends. */
.scroll .footline .quality-img{width:calc(var(--panel) * 0.22167);left:calc(var(--panel) * 0.70125)}

/* --- Backgrounds -------------------------------------------------------------
   Home keeps the photo. Every other screen is one flat colour — no photo, no
   vignette, no gradient, and the wave watermark is gone from the markup. */
:root{ --page-bg:#071B3A; }   /* the exact colour the client gave */
.bg{background:var(--page-bg)}
.bg-photo{opacity:0;transition:opacity 300ms ease}
/* no CSS filter: the photo dissolves into --page-bg, and a filter would lift that too */
body.at-home-bg .bg-photo{opacity:1;filter:none}
/* A soft top-and-bottom gradient, only on home: the brand block and the footline are
   white text over a photograph, and the photograph is not dark where they sit. */
.vign{opacity:0}
body.at-home-bg .vign{
  opacity:1;
  background:linear-gradient(180deg,
    rgba(3,10,22,0.60) 0%, rgba(3,10,22,0.26) 18%, rgba(3,10,22,0) 38%,
    rgba(3,10,22,0) 62%, rgba(3,10,22,0.34) 84%, rgba(3,10,22,0.62) 100%);
}
/* the About sheet was its own blue; it is the page colour now like everywhere else */
.screen[data-view="about"]{background:transparent}

/* Desktop: the app is a phone-width panel floating on the photo, so the photo has to
   step back or the panel stops reading as the subject. Phones keep the bright photo. */
@media (min-width:900px){
  body.at-home-bg .bg-photo{filter:none}
}


.docfeat{
  /* Full width, not 58%: he asked for the registration to be shown as large as it can
     be. It is 1.7x what it was — the body text goes from 2.5px to 3.8px on a phone,
     which is bigger but still not readable without opening it, because an A4 page at
     390px cannot be. Tapping to open is what makes it readable. */
  display:block;width:100%;margin:14px auto 0;padding:0;
  background:none;border:0;cursor:pointer;-webkit-tap-highlight-color:transparent;
  border-radius:2px;overflow:hidden;
  box-shadow:0 2px 14px rgba(0,0,0,0.45);
  transition:transform 150ms ease, box-shadow 150ms ease;
}
.docfeat img{display:block;width:100%;height:auto}
.docfeat:hover{transform:translateY(-1px);box-shadow:0 6px 20px rgba(0,0,0,0.55)}
.docfeat:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* section head: centred caps with a hairline reaching both edges */
.dochead-rule{
  display:flex;align-items:center;gap:9px;
  margin:20px 0 10px;
}
.dochead-rule::before,.dochead-rule::after{
  content:"";flex:1 1 auto;height:1px;background:rgba(47,123,255,0.34);
}
.dochead-rule span{
  flex:0 0 auto;
  font-family:Archivo,Barlow,Helvetica,sans-serif;
  font-size:9.5px;font-weight:600;letter-spacing:0.09em;color:#2f7bff;text-transform:uppercase;
}

.docgrid{display:grid;grid-template-columns:repeat(5,1fr);gap:5.5px;align-items:start}
/* every tile is the same white card whatever the certificate's own proportions are —
   the client's grid is a tidy 5x2 of equal boxes, not a ragged one */
.doctile{
  display:flex;aspect-ratio:67/80;padding:0;background:#fff;border:0;cursor:pointer;
  -webkit-tap-highlight-color:transparent;border-radius:2px;overflow:hidden;
  box-shadow:0 1px 6px rgba(0,0,0,0.4);
  transition:transform 150ms ease, box-shadow 150ms ease;
}
.doctile picture{display:block;width:100%;height:100%}
.doctile img{display:block;width:100%;height:100%;object-fit:contain}
.doctile:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(0,0,0,0.55)}
.doctile:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* the five columns are 62px wide on a phone; below three of them a certificate is a
   smudge rather than a document, so narrow screens drop to four */
@media (max-width:359px){
  .docgrid{grid-template-columns:repeat(4,1fr)}
}

/* --- "Still working on this page" (inc/wip.php) -------------------------------
   The owner's own design: a bordered navy panel, one bold line, one italic blue line.
   Sizes are a little under his drawing — he asked for it smaller. It sits directly
   under the title on every screen except home. */
/* Half the height he first drew, at his request of 2026-09-05 — the panel had grown into
   the loudest thing on every screen. The WIDTH is untouched: it still runs the full column,
   which is what holds the page together. Measured: 77px tall before, 39px after. */
.wip{
  /* The frame ends where the words end (2026-09-06). fit-content sizes it to the longest
     line; max-width keeps it inside the column on a narrow phone, where the line wraps
     and the frame follows it instead of running off the screen. */
  width:-webkit-fit-content;width:fit-content;max-width:100%;
  margin:2px auto 12px;padding:5px 18px;
  border:1px solid var(--accent);border-radius:5px;
  background:rgba(6,20,42,0.72);
  text-align:center;
}
.wip-h{margin:0;font-size:11px;font-weight:700;letter-spacing:-0.005em;color:#f4f8ff;line-height:1.25}
.wip-p{margin:2px 0 0;font-size:9.5px;color:#5aa4ff;line-height:1.25}

/* --- Footer: rules either side of ACROSS CANADA -------------------------------
   From his screenshot — the line runs out to both edges of the content, which is what
   makes the page look finished rather than cut off. */

/* --- Documents: registration line and payment instructions --------------------
   His layout, 2026-08-28: the corporation number sits under the certificate, and the
   ways to pay are rows that open. They are <details>, so no script is involved. */
.doc-company{
  margin:10px 0 0;text-align:center;font-size:14px;line-height:1.45;color:var(--ink);
}
.doc-company b{font-weight:700}
/* The corporation number copies itself. It has to keep reading as part of the sentence,
   so the button carries no chrome of its own until it is touched. */
.corpno{
  display:inline-flex;align-items:center;gap:5px;
  padding:1px 5px;margin:0 -2px;border:0;border-radius:6px;
  background:transparent;color:var(--accent);font:inherit;line-height:inherit;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:background 140ms ease, color 140ms ease;
}
.corpno b{font-weight:700;color:inherit}
.corpno:hover{background:rgba(47,123,255,0.14)}
.corpno:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* the word COPY, in the pill the Payment screen already uses */
.corpno-tag, .corpno-done{
  flex:0 0 auto;padding:3px 8px;border-radius:7px;
  border:1px solid rgba(90,150,235,0.45);background:rgba(9,32,70,0.75);
  color:#9fc4f2;font-size:10.5px;font-weight:600;letter-spacing:0.06em;
  text-transform:uppercase;line-height:1;
}
.corpno:hover .corpno-tag{border-color:rgba(130,190,255,0.85);color:#e6f1ff}
.corpno-done{display:none;border-color:rgba(90,220,150,0.7);background:rgba(9,48,32,0.75);color:#bff3d6}
.corpno.is-done .corpno-tag{display:none}
.corpno.is-done .corpno-done{display:inline-block}
.doc-note{margin:6px 0 0;text-align:center;font-size:12px;color:var(--sub)}
/* the same note over the photo grid: it needs air under it, not over it */
.gal-note{margin:2px 0 8px}

/* --- Payment screen ----------------------------------------------------------
   Five cards in the owner's order: e-Transfer, direct deposit, cheque, wire, invoice.
   Two of them carry a button instead of the details, because publishing a bank account
   on a page hands it to every crawler that ever reads the site.
   The strip at the top only exists when the owner is signed in. */
.payadmin{
  margin:14px 0 6px;padding:12px 13px;border-radius:14px;
  background:linear-gradient(180deg,#062a56 0%,#03142d 100%);
  border:1px solid rgba(70,130,210,0.34);
}
.payadmin-who{display:block;font-size:11.5px;letter-spacing:0.06em;text-transform:uppercase;color:#7fa8dd}
.payadmin-row{display:flex;flex-wrap:wrap;gap:7px;margin-top:9px}
/* a third weight of button: present, but not asking to be pressed */
.abtn-quiet{background:transparent;border-color:rgba(90,140,210,0.35);color:#9fbde2}
.abtn-quiet:hover:not(:disabled){border-color:rgba(120,180,255,0.7);color:#dbe9fb}
.payadmin-hint{margin:9px 0 0;font-size:11.5px;line-height:1.45;color:#8fa9ca}
.payadmin-note{
  margin:10px 0 0;padding:8px 10px;border-radius:9px;font-size:12.5px;line-height:1.4;
  border:1px solid rgba(90,140,210,0.4);color:#dbe7f8;
}
.payadmin-note.is-good{border-color:rgba(90,220,150,0.5);color:#c9f7de}
.payadmin-note.is-warn{border-color:rgba(240,190,90,0.55);color:#ffe9be}
.payadmin-note.is-bad{border-color:rgba(255,120,120,0.55);color:#ffd6d6}

.paycards{display:flex;flex-direction:column;gap:12px;margin-top:14px}
.paycard{
  padding:14px 15px 15px;border-radius:16px;
  background:linear-gradient(180deg,#041b39 0%,#03142d 100%);
  border:1px solid #243551;
}
.paycard-h{display:flex;align-items:center;gap:9px;color:#3b98ff}
.paycard-h h2{
  margin:0;font-size:13px;font-weight:700;letter-spacing:0.09em;color:#f2f6fd;
}
/* the way he wants to be paid, said once, next to the heading */
.paybadge{
  flex:0 0 auto;padding:3px 7px 2px;border-radius:6px;
  background:#2f7bff;color:#fff;
  font-size:9px;font-weight:800;letter-spacing:0.1em;line-height:1.3;white-space:nowrap;
}
.paycard-p{margin:9px 0 0;font-size:13.5px;line-height:1.5;color:#c4d4ea}
.paycard-note{margin:9px 0 0;font-size:12px;line-height:1.45;color:#8fa9ca}

/* Label on its own line, value under it — he asked for that on the cheque card and it
   reads better everywhere. The copy button is there because nobody should retype an
   account name or a postal code off a phone. */
.payfact{
  margin-top:10px;padding:9px 11px;border-radius:10px;
  background:rgba(6,26,60,0.6);border:1px solid rgba(70,130,210,0.22);
}
.payfact-k{
  display:block;font-size:10px;letter-spacing:0.09em;text-transform:uppercase;color:#7fa8dd;
}
.payfact-row{display:flex;align-items:flex-start;gap:10px;margin-top:4px}
.payfact-v{flex:1 1 auto;min-width:0;font-size:14px;font-weight:600;color:#1587fb;line-height:1.4;word-break:break-word}
/* The e-Transfer address is the one string on this page a customer has to copy
   correctly, so it is set well above everything around it. */
.payfact-big .payfact-v{font-size:min(20px, calc(var(--panel) * 0.0465));font-weight:700;letter-spacing:-0.005em}
.payfact-big{padding:11px 11px 12px}
a.payfact-v{text-decoration:none}
a.payfact-v:hover{text-decoration:underline}
.copybtn{
  flex:0 0 auto;margin-top:-1px;padding:4px 9px;border-radius:7px;
  border:1px solid rgba(90,150,235,0.45);background:rgba(9,32,70,0.75);
  color:#9fc4f2;font:inherit;font-size:10.5px;font-weight:600;letter-spacing:0.06em;
  text-transform:uppercase;cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:border-color 140ms ease, color 140ms ease, background 140ms ease;
}
.copybtn:hover{border-color:rgba(130,190,255,0.85);color:#e6f1ff}
.copybtn.is-done{border-color:rgba(90,220,150,0.7);color:#bff3d6;background:rgba(9,48,32,0.7)}
.copybtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.paybtn{
  display:block;width:100%;margin-top:12px;padding:12px 14px;
  border-radius:12px;border:1px solid rgba(90,160,255,0.55);
  background:linear-gradient(180deg,#0b3f8f 0%,#072a63 100%);
  color:#eaf3ff;font:inherit;font-size:13.5px;font-weight:600;letter-spacing:0.01em;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:border-color 150ms ease, background 150ms ease;
}
.paybtn:hover{border-color:rgba(120,190,255,0.9);background:linear-gradient(180deg,#0e4aa6 0%,#093275 100%)}
.paybtn:active{background:#062a5f}
.paybtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.req{font-style:normal;color:#ff9d6b;margin-left:3px}
.field-hint{margin:10px 0 0;font-size:11.5px;color:#8fa9ca;line-height:1.4}

/* Turnstile draws itself here; the box only takes space once it has something in it */
.cf-holder:not(:empty){margin:12px 0 2px;min-height:65px}

/* the desktop-only note under the frame; section 10 turns it on */
/* the honeypot: reachable by a bot reading the DOM, invisible and unfocusable to a person */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* invoice lines in the owner's dialog */
.field-label-alone{display:block;margin:14px 0 6px}
/* a grid item will not shrink below its content unless it is told it may, and an
   input's intrinsic width is wide — without min-width:0 the row runs off the card */
.invrow{display:grid;grid-template-columns:minmax(0,1fr) 2.9em 4.6em 1.3em;gap:5px;margin-bottom:7px;align-items:center}
.invrow>*{min-width:0}
.invrow .field-input{margin:0;padding:9px 8px;font-size:13px}
.invrow-qty,.invrow-rate{text-align:right}
.invrow-x{
  background:none;border:0;padding:4px 6px;color:#7fa8dd;font-size:13px;cursor:pointer;line-height:1;
}
.invrow-x:hover{color:#ff9d9d}

/* --- the estimate request on Pricing ------------------------------------- */
/* Same card as the Payment screen, holding the fields the dialogs use, so the two
   screens do not look like they were built by different people. */
.estcard{
  margin-top:14px;padding:15px 15px 16px;border-radius:16px;
  background:linear-gradient(180deg,#041b39 0%,#03142d 100%);
  border:1px solid #243551;
}
/* Four paragraphs of his introduction, then the same voice again under the form. One
   size, one weight, a plain gap between paragraphs — nothing here is a heading. */
.est-lead{margin:0;font-size:14px;font-weight:400;line-height:1.45;color:#dce7f6}
/* The closing line of the introduction is a suggestion about what to write, not part
   of the case for asking — so it is set greyer and a size down from the three above it. */
/* Everything that is a note rather than the argument is set at the site's note size and
   the site's grey — the same as .doc-note and .field-hint. In the copy's own size and
   colour these lines read as more of the copy, which is exactly what he objected to. */
.est-lead-quiet{margin-top:8px;color:var(--sub);font-size:12px;line-height:1.42}
.est-after{margin-top:14px;display:flex;flex-direction:column;gap:6px;
  font-size:12px;line-height:1.42;color:var(--sub)}
.est-after p{margin:0}
.est-after-note{font-size:11.5px;color:#7f93a9}
/* the second half of his lead, set quieter, the way his mockup has it */
.est-sub{margin:9px 0 0;font-size:13px;line-height:1.5;color:#a9bdd8;font-weight:400}

/* what happens after the button: his panel, bordered, with the last line quieter */
.estnext{
  margin:14px 0 0;padding:13px 14px;border-radius:12px;
  border:1px solid rgba(70,130,210,0.22);background:rgba(6,26,60,0.5);
}
.estnext p{margin:0;font-size:13px;line-height:1.5;color:#dce8f7;font-weight:600}
.estnext p + p{margin-top:9px}
.estnext .estnext-quiet{margin-top:12px;font-weight:400;color:#8fa9ca}
.estform{display:flex;flex-direction:column;gap:12px;margin-top:16px}
.estform textarea.field-input{line-height:1.45;resize:vertical}
.est-hint{margin:0}

/* The picker is a label so the whole strip is the tap target; the input inside it is
   what the browser opens, and hiding it with display:none would take it out of the
   keyboard's reach, so it is made invisible instead. */
.estpick{
  display:flex;align-items:center;justify-content:center;gap:8px;
  min-height:46px;padding:11px 12px;border-radius:10px;
  border:1px dashed rgba(90,150,235,0.5);background:rgba(6,26,60,0.5);
  color:#9fc4f2;font-size:13.5px;font-weight:600;letter-spacing:0.02em;
  position:relative;overflow:hidden;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:border-color 140ms ease, color 140ms ease, background 140ms ease;
}
.estpick:hover{border-color:rgba(130,177,255,0.8);color:#d5e7ff;background:rgba(9,32,70,0.75)}
.estpick-in{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.estpick-in:focus-visible + .estpick-t{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}
.estpick-t::before{content:'+';margin-right:7px;font-size:15px;line-height:1}

.estfiles{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.estfiles:not(:empty){margin-top:9px}
.estfile{
  display:flex;align-items:center;gap:10px;
  padding:6px 8px 6px 6px;border-radius:10px;
  background:rgba(6,26,60,0.6);border:1px solid rgba(70,130,210,0.22);
}
.estfile-img{flex:0 0 auto;width:38px;height:38px;border-radius:7px;object-fit:cover;display:block}
.estfile-n{flex:1 1 auto;min-width:0;font-size:12.5px;color:#c4d4ea;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.estfile-s{flex:0 0 auto;font-size:11px;color:#7fa8dd}
.estfile-x{
  flex:0 0 auto;background:none;border:0;padding:4px 4px;margin:0;
  color:#7fa8dd;font-size:13px;line-height:1;cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.estfile-x:hover{color:#ff9d9d}

.est-msg{margin:2px 0 0;font-size:13px;line-height:1.45;color:#c4d4ea}
.est-msg.is-good{color:#7fe0a8}
.est-msg.is-bad{color:#ff9d9d}
.est-msg.is-warn{color:#ffcf8f}

/* --- the Canada block, beside the phone ---------------------------------- */
/*
   The client's brief of 2026-08-30: on a computer or a tablet the free space beside the
   phone carries an outline of Canada with the reason the site looks like a phone; under
   768px the block does not exist at all.

   ONE NUMBER SIZES IT: --canada-w. The block is a single image, so the outline, the words,
   the leaf and every gap between them scale together by construction, which is the
   client's "the whole block scales as a single object".

   THE SIZE IS 15% OF THE SCREEN, floored at 200px and capped at 300px. The client's own
   figure was 6-6.5% (85-130px) and it shipped that way first; 10% on 2026-08-31 and 15% on
   2026-09-02, each time after seeing it — the writing inside had to be readable. At that width the writing inside the
   outline is about six pixels tall — it is texture, not something anyone reads, and that
   is a decision taken deliberately after seeing it larger. The words are still positioned
   properly and kept clear of the coastline, so it holds up if it is ever enlarged again:
   one line changes it.

   It is the client's own picture, lifted off its black ground into an image with real
   transparency — see inc/canada.php and _ref/cut-canada-artwork.js. Nothing inside it is
   text any more, so nothing inside needs sizing: the width below sizes the whole thing.

   The block never overlaps the site: its width is also capped by whatever is actually left
   beside the panel, and it is pinned to the bottom right of that space.
*/
.canada{display:none}

@media (min-width:768px){
  .canada{
    --canada-w: clamp(200px, 15vw, 300px);
    /* what it is actually drawn at, once the free column has had its say */
    --cw: min(var(--canada-w), calc((100vw - var(--panel-raw)) / 2 - 28px));
    /* the panel the home canvas uses: the outer one, capped by a short window */
    --home-panel: min(var(--panel-raw), calc(100dvh / 1.76667));
    display:block;
    position:fixed;
    /* Centred across the free column, not pinned to the corner: the column runs from
       the right edge of the panel to the right edge of the window, so its middle is
       75% of the window plus a quarter of the panel. */
    left:calc(75% + var(--panel-raw) / 4);
    transform:translateX(-50%);
    /* level with the Quality First mark inside the frame, not sunk to the bottom edge:
       the mark's middle sits that far up from the foot of the window, and the block is
       dropped by half its own height so the two middles meet */
    /* The -37px is not a fudge to taste: with the rest of the expression in place the
       block landed a measured 42-50px above the mark at seven window sizes, so this is
       that offset taken back out. Verified after, not assumed. */
    bottom:max(14px, calc(50dvh - var(--home-panel) * 0.502 - 37px - var(--cw) / 2.562));
    width:var(--cw);
    z-index:2;
    pointer-events:none;          /* decoration: it must never eat a click */
    opacity:1;
  }
  .canada picture{display:block}
  .canada-img{display:block;width:100%;height:auto}
}

/* a short window has no room for it beside a full-height panel */
@media (min-width:768px) and (max-height:520px){
  .canada{display:none}
}

/* An icon that is a picture, not a path — see ICON_IMAGE in inc/icons.php. Painted as a
   mask so it takes currentColor exactly like the drawn icons beside it. */
.icon-img{
  display:inline-block;flex:0 0 auto;max-width:100%;
  background-color:currentColor;
  -webkit-mask-image:var(--icon-src);mask-image:var(--icon-src);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
}
