/* OIC site layer. Nova's tokens.css is loaded FIRST and owns the palette,
   type, radii, hairlines and slot ratios. This file only composes layout. */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--oic-concrete-050);color:var(--oic-concrete-700);
 font:400 1rem/1.65 var(--font-body);-webkit-font-smoothing:antialiased}
img{max-width:100%;height:auto;display:block}
h1,h2,h3{font-family:var(--font-display);color:var(--oic-concrete-900);
 letter-spacing:var(--tracking-display);line-height:1.1;margin:0 0 .45em;font-weight:700}
h1{font-size:clamp(2.1rem,5.4vw,3.4rem)}
h2{font-size:clamp(1.5rem,3.2vw,2.15rem)}
h3{font-size:clamp(1.05rem,1.9vw,1.25rem)}
p{margin:0 0 1.1rem;max-width:var(--measure)}
a{color:var(--oic-accent-deep)}
:focus-visible{outline:2px solid var(--oic-accent);outline-offset:2px}
.wrap{width:100%;max-width:1180px;margin:0 auto;padding:0 clamp(1rem,4vw,2rem)}
.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;z-index:99;background:#fff;padding:10px 14px}

/* grid lines as the layout motif — furniture systems are modular */
.lattice{position:relative}
.lattice::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
 background-image:linear-gradient(90deg,var(--oic-concrete-300) 1px,transparent 1px);
 background-size:calc(100% / 6) 100%;opacity:.4}
.lattice>*{position:relative;z-index:1}

/* header */
.head{position:sticky;top:0;z-index:60;background:var(--oic-concrete-050);
 border-bottom:var(--hairline)}
.head-in{display:flex;align-items:center;gap:1.25rem;min-height:64px;flex-wrap:wrap}
.brand{display:flex;align-items:baseline;gap:.5rem;text-decoration:none;margin-right:auto;
 color:var(--oic-concrete-900)}
.brand b{font:700 1.05rem/1 var(--font-display);letter-spacing:var(--tracking-display)}
.brand span{font:500 .72rem/1 var(--font-data);text-transform:uppercase;
 letter-spacing:var(--tracking-label);color:var(--oic-concrete-500)}
.navbtn{display:none;background:none;border:var(--hairline);border-radius:var(--radius);
 padding:10px 12px;min-width:44px;min-height:44px;cursor:pointer;color:var(--oic-concrete-900)}
.nav{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}
.nav a{color:var(--oic-concrete-700);text-decoration:none;font-size:.94rem;font-weight:500}
.nav a:hover{color:var(--oic-accent-deep)}
@media(max-width:768px){.navbtn{display:block;order:3}
 .nav{display:none;order:4;width:100%;flex-direction:column;align-items:flex-start;
  gap:0;border-top:var(--hairline);padding:.5rem 0 1rem}
 .nav.open{display:flex}.nav a{width:100%;padding:.8rem 0;border-bottom:var(--hairline)}}

/* Nav CTA text colour — Stace, 2026-09-30.
   The nav CTA is <a class="btn"> inside .nav. `.nav a` is (0,1,1) — class plus
   element — and `.btn` is only (0,1,0). So `.nav a` WON and the button
   inherited concrete-700, rendering dark text on the blue ground. Every
   byte-check passed it: the rule was there, the guard never looked at nav
   text, and only a human seeing the rendered page could catch it.
   .nav a.btn (0,2,1) outranks both. Hover needed fixing too — `.nav a:hover`
   would have painted it navy-on-navy. */
.nav a.btn,.nav a.btn:visited{color:#fff}
.nav a.btn:hover,.nav a.btn:focus-visible{color:#fff}

/* THE one earned accent: a single CTA per viewport */
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:48px;
 padding:.75rem 1.5rem;background:var(--oic-accent);color:#fff;border:none;
 border-radius:var(--radius);font-weight:600;font-size:.95rem;text-decoration:none;cursor:pointer}
.btn:hover{background:var(--oic-accent-deep);color:#fff}
.btn:only-of-type{background:var(--oic-accent)}

/* HERO — graphic field, full bleed, headline in centre-left negative space */
.hero{position:relative;background:var(--oic-concrete-900);overflow:hidden;
 min-height:clamp(380px,58vw,620px);display:flex;align-items:center}
 /* v-fixed: the hero was pinned to aspect-ratio 16/9, so at desktop width the box came out
    ~675px and the CTA clipped in half at the fold. Caught by LOOKING at the rendered page, not
    by any grep — bytes and status codes were all green while the button was cut off screen.
    Same principle as slot D: don't pin the ratio, cover-fit the graphic and let content set
    the height. The image is absolutely positioned and covers whatever height results. */
.hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
.hero-in{position:relative;z-index:2;padding-block:clamp(2.5rem,7vw,4.5rem);width:100%}
.hero-copy{max-width:min(56ch,62%)}
.hero h1{color:#fff;margin-bottom:.5rem}
.hero .lede{color:rgba(255,255,255,.9);font-size:clamp(1rem,1.6vw,1.12rem)}
.hero .oic-eyebrow{color:rgba(255,255,255,.82)}
.hero .btn{background:var(--oic-accent)}
/* The graphic is a full-bleed OVERLAY at every width — never a flex sibling of the copy.
   Two bugs lived here, both reported by Nova's render pass and invisible to every byte check:
   (1) this query set .hero-img to position:relative, making the <picture> a flex item
       beside .hero-in, so the field became a small tile and the copy a narrow column;
   (2) nothing ever sized the <img> INSIDE the <picture> — object-fit on a <picture> is
       inert, so the image never filled its box.
   The H1 also flipped to dark concrete while the image still lay over it: white text on
   the field became dark text on the same dark field, which is why the H1 was invisible
   at 375. Copy stays light over the field at every width, over a scrim. */
.hero-img img{width:100%;height:100%;object-fit:cover;object-position:center;display:block}
.hero::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
 background:linear-gradient(100deg,rgba(12,22,58,.86) 0%,rgba(12,22,58,.66) 45%,rgba(12,22,58,.38) 100%)}
@media(max-width:1024px){
  .hero{min-height:clamp(420px,88vw,560px);align-items:flex-end}
  .hero-in{padding-block:2rem 2.25rem}
  .hero-copy{max-width:none}
  .hero .lede{font-size:1rem}
  .hero::after{background:linear-gradient(180deg,rgba(12,22,58,.54) 0%,rgba(12,22,58,.88) 62%)}
}

/* fact strip — mono, because these are facts not feelings */
/* Facts strip. Carl, 2026-09-30: at 375 the 2x2 gave each label about 160px while the
   labels are full sentences, so they wrapped to different line counts and the four numbers
   stopped reading as a row. A 2x2 grid of long copy is the wrong shape at that width.
   Below md the strip is four full-width rows — number and label share one baseline and the
   label gets the whole 343px. The grid returns at md and lg exactly as before.
   Gap-plus-background also fixes a stray rule: border-right on every cell cleared only on
   :last-child, which left a rule hanging on the outer edge at two columns. */
.facts{border-block:var(--hairline);background:#fff}
.facts-in{display:grid;grid-template-columns:1fr;gap:1px;background:var(--oic-concrete-300)}
@media(min-width:768px){.facts-in{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1024px){.facts-in{grid-template-columns:repeat(4,1fr)}}
.facts-in>div{background:#fff;padding:1.15rem clamp(1rem,3vw,1.6rem);
 display:flex;align-items:baseline;gap:.9rem}
/* The 1px gap shows .facts-in's own background as the rule between cells, so .facts-in must
   be edge-to-edge. It is a child of .wrap, not .wrap itself — otherwise the wrap's horizontal
   padding exposed the grid background as a grey frame around the whole strip. */
.facts b{font:600 1.45rem/1 var(--font-data);color:var(--oic-concrete-900);
 letter-spacing:var(--tracking-label);font-variant-numeric:tabular-nums;flex:none}
.facts span{font-size:.84rem;color:var(--oic-concrete-500);line-height:1.45}
@media(min-width:768px){
 .facts-in>div{display:block;padding:1.4rem clamp(1rem,3vw,1.6rem)}
 .facts b{font-size:1.6rem}
 .facts span{display:block;margin-top:.45rem}
}

/* sections */
.band{padding-block:var(--section-pad)}
.band-alt{background:#fff;border-block:var(--hairline)}
.sec-lede{color:var(--oic-concrete-500);max-width:var(--measure);margin-bottom:2.25rem}

/* service tiles — Nova's exact macro assignment, 1:1 */
.grid-svc{display:grid;gap:1px;background:var(--oic-concrete-300)}
@media(min-width:768px){.grid-svc{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1024px){.grid-svc{grid-template-columns:repeat(3,1fr)}}
.tile{background:#fff;display:flex;flex-direction:column}
.tile figure{margin:0;aspect-ratio:var(--slot-macro);overflow:hidden;background:var(--oic-concrete-100)}
.tile figure img{width:100%;height:100%;object-fit:cover}
.tile-b{padding:1.4rem 1.4rem 1.6rem;display:flex;flex-direction:column;flex:1}
.tile h3{margin-bottom:.4rem}
.tile h3 a{color:var(--oic-concrete-900);text-decoration:none}
.tile h3 a:hover{color:var(--oic-accent-deep)}
.tile p{font-size:.93rem;margin-bottom:.9rem}
.tile .more{margin-top:auto;font:500 .82rem/1 var(--font-data);text-transform:uppercase;
 letter-spacing:var(--tracking-label);color:var(--oic-concrete-500);text-decoration:none}
.tile .more:hover{color:var(--oic-accent-deep)}

/* spec table — locations, against the kraft field. No photos, by decision. */
.spec{width:100%;border-collapse:collapse;background:rgba(255,255,255,.86)}
.spec caption{text-align:left;padding-bottom:.9rem;color:var(--oic-concrete-700);font-size:.92rem}
.spec th,.spec td{text-align:left;padding:1rem 1.1rem;border-bottom:var(--hairline);vertical-align:top}
.spec thead th{font:500 .72rem/1 var(--font-data);text-transform:uppercase;
 letter-spacing:var(--tracking-label);color:var(--oic-concrete-500);border-bottom:1px solid var(--oic-concrete-700)}
.spec tbody th{font-family:var(--font-display);font-size:1.05rem;color:var(--oic-concrete-900);font-weight:700}
/* Nova's rule: one accent per viewport — the CTA earns the orange, nothing else does.
   Four orange city links made the locations view read as busy. The names are the CONTENT
   of this page, so they take the ink and a hairline underline. */
.spec tbody th a,.spec tbody th a:visited{color:var(--oic-concrete-900);text-decoration:none;
 border-bottom:1px solid var(--oic-concrete-300);padding-bottom:1px}
.spec tbody th a:hover{color:var(--oic-concrete-900);border-bottom-color:var(--oic-concrete-900)}
.spec td{font-size:.93rem}
.spec .oic-fact{color:var(--oic-concrete-700)}
.spec-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* split */
.split{display:grid;gap:var(--grid-gap);align-items:start}
@media(min-width:1024px){.split{grid-template-columns:1.05fr .95fr}}
.split figure{margin:0;aspect-ratio:var(--slot-macro);overflow:hidden;background:var(--oic-concrete-100)}
.split figure img{width:100%;height:100%;object-fit:cover}

.checks{list-style:none;padding:0;margin:1.5rem 0 0;max-width:var(--measure)}
.checks li{position:relative;padding-left:1.6rem;margin-bottom:.6rem;font-size:.95rem}
.checks li::before{content:"";position:absolute;left:0;top:.62em;width:9px;height:2px;
 background:var(--oic-accent)}

/* caution + verify: semantic, sparse, specific */
.caution{border-left:2px solid var(--oic-caution);padding-left:1rem;margin:1.25rem 0 0;
 font-size:.9rem;color:var(--oic-concrete-700);max-width:var(--measure)}
.note-verify{border-left:2px solid var(--oic-verify);padding-left:1.1rem}

/* page head */
.page-head{background:#fff;border-bottom:var(--hairline)}
.page-head .wrap{padding-block:clamp(2.5rem,6vw,4rem)}

/* service detail rows */
.svc-row{display:grid;gap:var(--grid-gap);padding-block:clamp(1.75rem,4vw,2.5rem);
 border-bottom:var(--hairline);align-items:center;scroll-margin-top:80px}
@media(min-width:1024px){.svc-row{grid-template-columns:1fr 300px}}
.svc-row:last-child{border-bottom:0}
.svc-row figure{margin:0;aspect-ratio:var(--slot-macro);overflow:hidden;background:var(--oic-concrete-100)}
.svc-row figure img{width:100%;height:100%;object-fit:cover}
.svc-num{font:600 .8rem/1 var(--font-data);color:var(--oic-concrete-300);letter-spacing:var(--tracking-label)}

/* form */
.form{background:#fff;padding:clamp(1.25rem,3vw,2rem);border:var(--hairline)}
.row{margin-bottom:1.1rem;display:flex;flex-direction:column;gap:.35rem}
label{font:500 .78rem/1 var(--font-data);text-transform:uppercase;
 letter-spacing:var(--tracking-label);color:var(--oic-concrete-500)}
input,select,textarea{width:100%;padding:.75rem .85rem;border:var(--hairline);
 border-radius:var(--radius);font:inherit;color:var(--oic-concrete-900);background:#fff;min-height:48px}
input:focus,select:focus,textarea:focus{border-color:var(--oic-accent);outline:2px solid var(--oic-accent-soft)}
textarea{resize:vertical}

/* footer */
.foot{background:var(--oic-concrete-900);color:var(--oic-concrete-300);margin-top:auto}
.foot-in{display:grid;gap:2rem;padding-block:clamp(2.5rem,6vw,3.5rem)}
@media(min-width:768px){.foot-in{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1280px){.foot-in{grid-template-columns:2fr 1fr 1fr 1fr}}
.foot b{color:#fff;font-family:var(--font-display);display:block;margin-bottom:.5rem}
.foot h4{font:500 .74rem/1 var(--font-data);text-transform:uppercase;
 letter-spacing:var(--tracking-label);color:var(--oic-concrete-300);margin:0 0 .9rem}
.foot ul{list-style:none;padding:0;margin:0}.foot li{margin-bottom:.5rem;font-size:.9rem}
.foot a{color:var(--oic-concrete-300);text-decoration:none}
.foot a:hover{color:#fff;text-decoration:underline}
.foot-legal{border-top:1px solid rgba(255,255,255,.14);padding-block:1.25rem}
.foot-legal p{margin:0;font-size:.8rem;max-width:none}
body{display:flex;flex-direction:column;min-height:100vh}
main{flex:1}
@media print{.head,.btn{display:none}}

/* SLOT D — dock band. Delivered graphic field, not a photo stand-in and not a flat colour.
   Carl (2026-09-30): field-b-light-21x9 is 1536x658 = 2.334:1, which IS 21:9 to three decimals.
   So: cover-fit the image and let the band be as tall as the design wants.
   Pinning the band to a fixed 21 by 9 ratio would letterbox by a hair. min-height keeps it a real band on narrow
   viewports without cropping the graphic to a sliver. */
.dock{position:relative;overflow:hidden;background:var(--oic-kraft);border-block:var(--hairline)}
.dock-img{position:absolute;inset:0;width:100%;height:100%;display:block}
.dock-img img{width:100%;height:100%;object-fit:cover;object-position:center;display:block}
@media(min-width:768px){.dock{min-height:clamp(140px,16vw,260px)}}
@media(max-width:767px){.dock{min-height:120px}}

/* the kraft section keeps the delivered field as its ground, with the spec table on top */
.band-kraft{background:var(--oic-kraft);border-block:var(--hairline);position:relative;
 background-image:url('/assets/field-b-light-21x9.png');background-size:cover;background-position:center}
.band-kraft>.wrap{position:relative;z-index:1}
/* Nova's pairing rule (tokens.css, in-file): on kraft, text a reader must parse is
   ALWAYS --oic-concrete-900. The spec table's caption and cells sit on the kraft band,
   so the caption inherits that rule here rather than globally — the same table is not
   on kraft elsewhere. concrete-500 and concrete-700 as kraft captions are prohibited;
   see contrast-check.mjs, which now asserts this pairing against the stylesheet. */
/* Nova's hierarchy on kraft (a59e734, ruling 2026-09-30):
     concrete-900  7.50:1  headings, emphasis, TABLE HEADERS
     concrete-700  5.15:1  body copy, captions, TABLE CELLS
   I had pushed cells and the caption to 900 as well. That was my over-correction: it
   flattened the hierarchy she was defending, and it threw away the 700/900 distinction
   the table exists to show. Reverted to her pairing.
   700 itself is darkened (#3a3e40 -> #363a3c) because 4.84:1 was measured against FLAT
   nominal kraft, while the live band is the field-b texture whose local lightness varies
   — a nominal pass is a best case, not a typical one. The new value buys headroom
   over AA on the texture and costs nothing on the light ground. */
.band-kraft .spec caption,.band-kraft .spec td{color:var(--oic-concrete-700)}
.band-kraft .spec th{color:var(--oic-concrete-900)}
/* The eyebrow ("Locations") is concrete-500 at 12px directly on the kraft band. Nova's
   tokens.css forbids concrete-500 as text on kraft at any value — that is a published
   in-file rule, not a judgement call, so it is applied here rather than escalated. */
.band-kraft .oic-eyebrow{color:var(--oic-concrete-900)}
/* .sec-lede is deliberately NOT included. It renders concrete-700 on kraft at 16px/400,
   which measures 4.84:1 and therefore passes AA. Nova has not measured that pairing, so
   it stays UNRESOLVED and kraft-dom-check.mjs reports it as such. Darkening it to force
   the check green would answer her question for her. */
/* thead labels on kraft specifically: Nova's tokens.css states in-file that
   concrete-500 is not permitted as text on kraft at any value. Applied here rather than
   token-wide because the spec table is only on kraft in these two places. */

/* =====================================================================
   UI REFRESH — Nova, 2026-09-30. Stace brief: "too clunky", rounded
   buttons, minimal menu bar, splash animation, modernise mobile.
   APPENDED AS AN OVERRIDE LAYER rather than editing the rules above, so
   Pixel's guarded section (and the comments contrast-check.mjs reads)
   stays byte-identical and reversible with one `git revert`.

   PALETTE AND TYPE ARE UNCHANGED. Nothing here touches a colour token's
   value, and nothing here sets a text colour on the kraft band.
   ===================================================================== */

/* --- 1. Pill buttons -------------------------------------------------
   Rounding the ACTION surfaces only. The 2px card radius stays: a rounded
   card on a drafting-grid system reads as consumer SaaS, and the tiles and
   the spec table are structural, not pressable. Pills say "press this". */
.btn{border-radius:var(--radius-pill);padding:.8rem 1.75rem;
 transition:background-color .16s ease,transform .16s ease,box-shadow .16s ease;
 box-shadow:0 1px 2px rgba(18,24,32,.10)}
.btn:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(18,24,32,.16)}
.btn:active{transform:translateY(0);box-shadow:0 1px 2px rgba(18,24,32,.10)}
.nav .btn{padding:.55rem 1.15rem;min-height:40px;font-size:.88rem}

input,select,textarea{border-radius:var(--radius-md);padding:.8rem 1rem;transition:border-color .16s ease}

/* --- 2. Minimal menu bar ---------------------------------------------
   64px was tall for a bar carrying four links. Down to 56, tighter gap,
   smaller nav type, and a real scrolled state so the bar earns its
   height by getting out of the way rather than by being big. */
.head{background:rgba(242,240,236,.86);backdrop-filter:saturate(1.4) blur(10px);
 -webkit-backdrop-filter:saturate(1.4) blur(10px);transition:box-shadow .2s ease}
.head.is-stuck{box-shadow:0 1px 0 rgba(28,30,31,.06),0 6px 18px rgba(28,30,31,.07)}
.head-in{min-height:56px;gap:.9rem}
.brand{gap:.45rem}
.brand b{font-size:1rem}
.brand span{font-size:.68rem}
.nav{gap:1.15rem}
.nav a{font-size:.9rem;position:relative;padding-block:.2rem}
.nav a:not(.btn)::after{content:"";position:absolute;left:0;right:0;bottom:-2px;height:1px;
 background:currentColor;transform:scaleX(0);transform-origin:left;
 transition:transform .18s ease}
.nav a:not(.btn):hover::after{transform:scaleX(1)}
.navbtn{border-radius:var(--radius-pill);border-color:transparent;min-width:42px;min-height:42px;
 padding:8px 11px;font-size:1.05rem;line-height:1}

/* --- 3. Splash animation ---------------------------------------------
   A floor plan drawing itself, because furniture systems are modular and
   that is the whole brand thesis. Fine white lines on the delivered field,
   plus ONE orange diagonal that echoes field-a. It is decorative:
   aria-hidden, no text nodes, so the contrast and kraft guards still walk
   the same 21 nodes and cannot be moved by it.

   Z-ORDER IS THE POINT: field z0, PLAN z1, SCRIM z2, COPY z3. The plan sits
   UNDER the scrim on purpose. Putting it above would let a bright line pass
   behind the H1 and change the sampled background — and the guard measures
   the rendered pixel, so a decorative flourish could turn a passing page
   into a failing one. Under the scrim, the sampled background is unchanged. */
.hero-plan{position:absolute;inset:0;z-index:1;width:100%;height:100%;
 pointer-events:none;opacity:.62}
.hero-plan *{fill:none;stroke:rgba(255,255,255,.82);stroke-width:1.4;vector-effect:non-scaling-stroke}
.hero-plan .plan-accent{stroke:var(--oic-accent-light);stroke-width:1.8}
.hero::after{z-index:2;background:linear-gradient(100deg,rgba(12,22,58,.86) 0%,rgba(12,22,58,.66) 45%,rgba(12,22,58,.38) 100%)}
.hero-in{z-index:3}
/* ============================================================================
   SEAMLESS SPLASH LOOP — Stace, 2026-09-30: "make it loop, but clean so you
   can't tell it's a loop."

   THE PROBLEM WITH LOOPING A DRAW-ON: it has a definite end state, so the
   wrap from "fully drawn" back to "undrawn" is a visible snap. Spreading the
   stagger across animation-delay does NOT work, because each delayed child
   then RESETS at a different phase — one of them always snaps while the plan
   is visible, no matter which window you hide.

   THE FIX, two parts:
   1. The stagger is baked into each child's KEYFRAMES, not into
      animation-delay. Every child therefore shares ONE phase and resets at
      the same instant.
   2. The parent fades to opacity 0 BEFORE that instant. The reset happens at
      zero opacity, so there is nothing on screen to see it happen in.

   11.5s cycle: assemble (0-40%) -> hold (40-82%) -> fade out (82-92%) ->
   hidden reset (92-100%). The seam lives entirely in the last 8%.
   ============================================================================ */

@keyframes planBreathe{
 0%{opacity:0} 7%{opacity:.62} 82%{opacity:.62} 92%{opacity:0} 100%{opacity:0}
}
@keyframes planDraw0{ 0%{stroke-dashoffset:1} 0.0%{stroke-dashoffset:1} 19.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw1{ 0%{stroke-dashoffset:1} 3.0%{stroke-dashoffset:1} 22.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw2{ 0%{stroke-dashoffset:1} 6.0%{stroke-dashoffset:1} 25.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw3{ 0%{stroke-dashoffset:1} 9.0%{stroke-dashoffset:1} 28.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw4{ 0%{stroke-dashoffset:1} 12.0%{stroke-dashoffset:1} 31.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw5{ 0%{stroke-dashoffset:1} 15.0%{stroke-dashoffset:1} 34.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw6{ 0%{stroke-dashoffset:1} 18.0%{stroke-dashoffset:1} 37.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDraw7{ 0%{stroke-dashoffset:1} 21.0%{stroke-dashoffset:1} 40.0%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }
@keyframes planDrawAccent{ 0%{stroke-dashoffset:1} 24%{stroke-dashoffset:1} 44%{stroke-dashoffset:0} 100%{stroke-dashoffset:0} }

@media (prefers-reduced-motion:no-preference){
 .hero-plan{animation:planBreathe 11.5s linear infinite}
 .hero-plan>*{stroke-dasharray:1;animation-timing-function:cubic-bezier(.45,.05,.25,1);animation-iteration-count:infinite;animation-duration:11.5s}
 .hero-plan>*:nth-child(1){animation-name:planDraw0}
 .hero-plan>*:nth-child(2){animation-name:planDraw1}
 .hero-plan>*:nth-child(3){animation-name:planDraw2}
 .hero-plan>*:nth-child(4){animation-name:planDraw3}
 .hero-plan>*:nth-child(5){animation-name:planDraw4}
 .hero-plan>*:nth-child(6){animation-name:planDraw5}
 .hero-plan>*:nth-child(7){animation-name:planDraw6}
 .hero-plan>*:nth-child(8){animation-name:planDrawAccent}
}

/* Reduced motion: no animation, but the plan is still drawn. It is a floor
   plan, not a decoration — a blank hero would be worse than a static one. */

/* --- 4. Mobile modernization -----------------------------------------
   Stace: responsive is solid, make it modern. Phone gets rounded service
   tiles, pill CTAs at thumb height, a proper sheet nav, and roomier form
   fields. Breakpoints unchanged: sm640 / md768 / lg1024 / xl1280. */
@media(max-width:768px){
 .head-in{min-height:52px;padding-block:.5rem}
 .brand span{display:none}
 .btn{width:100%;padding-block:.9rem}
 .hero .btn{width:auto}
 /* nav as a floating sheet rather than a full-width stack */
 .nav{background:#fff;border:var(--hairline);border-radius:var(--radius-md);
  box-shadow:0 12px 32px rgba(28,30,31,.14);padding:.35rem;gap:0;
  margin-top:.6rem;overflow:hidden}
 .nav a{padding:.85rem .9rem;border-bottom:1px solid var(--oic-concrete-100);
  border-radius:6px;margin-bottom:2px}
 .nav a:last-child{border-bottom:0;margin-bottom:0}
 .nav a:not(.btn):hover{background:var(--oic-concrete-050)}
 .nav a:not(.btn)::after{display:none}
 .nav .btn{width:100%;margin-top:.35rem;border-bottom:0}
 /* tiles read as cards on a phone */
 .tile{background:#fff;border-radius:var(--radius-md);overflow:hidden;
  box-shadow:0 1px 2px rgba(28,30,31,.05)}
 .tile figure{aspect-ratio:16/10}
 .tile-b{padding:1.1rem 1.15rem 1.25rem}
 .tile p{font-size:.95rem}
 .facts-in>div{padding:1.05rem 1.1rem}
 input,select,textarea{min-height:52px;font-size:16px}
 .spec th,.spec td{padding:.85rem .9rem}
 .spec thead th{font-size:.68rem}
}
@media(prefers-reduced-motion:reduce){
 .btn,.nav a:not(.btn)::after{transition:none}
 .btn:hover{transform:none}
}
