
/* ============================================================
   STORYSCAPE TEMPLATE — storyscape-v2
   Authored 2026-08-29 against TEMPLATE-BRIEF.md and DESIGN-STANDARDS.md.

   Same class vocabulary as v1 — that vocabulary IS the builder contract.
   v2 restyles it; it renames nothing, so the builder needs no changes.

   Three structural departures from v1:
     1. Layout is content-driven. Grids state what a card needs and the browser
        derives the count, so 2/3/5/7 items work without a rule per case.
     2. Splits stack on the space the SECTION has (container query), not the
        viewport width — which is what let v1 squeeze text to 27 chars/line.
     3. One horizontal padding, not two. v1 paid the gutter twice, spending
        96px of a 320px phone on margins.

   Viewport media queries are kept only for page-level structure (the nav) and
   user preferences (reduced motion) — the two things container queries cannot
   express.
   ============================================================ */

:root{
  /* Type — 1.2 modular scale on a 16px base. Nine of the hand-built page's
     sizes already sat on this ratio; the eleven that did not are gone.
     Every clamp() carries a rem component and a max ≤2.5× its min, or it
     fails WCAG 1.4.4 under zoom. */
  --t-label:   clamp(0.75rem, 0.72rem + 0.15vw, 0.8125rem);  /* 12 → 13 */
  --t-small:   0.875rem;                                      /* 14      */
  --t-body:    1rem;                                          /* 16      */
  --t-lead:    clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);     /* 17 → 19 */
  --t-h3:      clamp(1.1875rem, 1.05rem + 0.6vw, 1.4375rem);  /* 19 → 23 */
  --t-h2:      clamp(1.625rem, 1.2rem + 2.1vw, 2.5rem);       /* 26 → 40 */
  --t-display: clamp(1.875rem, 1.25rem + 2.6vw, 3rem);        /* 30 → 48 */

  /* Spacing — 8px rhythm. The hand-built page's two largest values already
     fitted it: 56px split gaps (7×8), 88px section padding (11×8). */
  --s-1:8px; --s-2:16px; --s-3:24px; --s-4:32px; --s-5:48px; --s-6:56px; --s-7:88px;
  --gutter:   clamp(24px, 4vw, 56px);
  --section-y:clamp(48px, 8vw, 88px);
  --gap:      var(--s-3);

  /* Colour — five near-identical greys consolidated to three. No perceptible
     change; the brand is untouched. */
  --fg:#ffffff; --fg-body:#c4c4ce; --fg-muted:#8a8a92; --fg-invert:#0b0b0d;
  --accent:#ffce10; --accent-hi:#ffd94a;
  --accent-dim:rgba(255,206,16,0.1); --accent-line:rgba(255,206,16,0.4);
  --bg:#0b0b0d; --bg-alt:#0f0f12; --bg-card:#141418; --bg-deep:#08080a;
  --line:rgba(255,255,255,0.09); --line-mid:rgba(255,255,255,0.12); --line-strong:rgba(255,255,255,0.25);

  --r-ctl:12px; --r-card:18px; --r-media:22px; --r-pill:999px;
  --measure:66ch;
  --ease:0.15s ease;

  /* Sticky nav height, stated once. Sections use it as scroll-margin so a
     page-down or anchor jump never parks a heading underneath the bar.
     16px padding-block x2 + the 44px tap-target floor + 1px border. */
  --nav-h:77px;

  /* Content-driven grid defaults. --cols is a MAXIMUM: the browser fits fewer
     when a track would fall below --col-min. */
  --cols:3; --col-min:17rem;
}

*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
body{font-family:Montserrat,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  background:var(--bg);color:var(--fg);font-size:var(--t-body);line-height:1.6;text-wrap:pretty}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent-hi)}
a:focus-visible,button:focus-visible,[role="button"]:focus-visible,[tabindex]:focus-visible{
  outline:3px solid var(--accent);outline-offset:3px}
img{max-width:100%}

/* ── NAV ───────────────────────────────────────────────────
   Viewport-scoped by design: the nav is page structure, not a component
   adapting to its container. */
nav{background:var(--bg);padding:var(--s-2) var(--gutter);display:flex;align-items:center;
  justify-content:space-between;border-bottom:1px solid var(--line);position:sticky;top:0;z-index:100}
.navlogo{display:block;height:36px;width:auto;object-fit:contain}
nav a{display:inline-flex;align-items:center;min-height:44px}
.nav-logo{font-weight:900;font-size:var(--t-h3);letter-spacing:-0.01em;text-transform:uppercase;color:var(--fg)}
.nav-logo span{color:var(--accent)}
.nav-links{display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap}
.nav-links a{color:var(--fg-body);font-size:var(--t-small);font-weight:600;display:inline-flex;align-items:center;min-height:44px}
.nav-links a:hover{color:var(--fg)}
/* min-height stays 44px — that is the tap-target floor, not a look. Only the
   padding and label size come down, which is what made it read as oversized. */
.nav-links a.nav-cta{background:var(--accent);color:var(--fg-invert);font-weight:800;
  padding:8px 16px;border-radius:var(--r-ctl);min-height:44px;display:inline-flex;align-items:center}
.nav-links a.nav-cta:hover{background:var(--accent-hi);color:var(--fg-invert)}
@media(max-width:900px){.nav-links{display:none}.navlogo{height:30px}}
/* A short viewport spends a far larger share of itself on the bar than a tall
   one does. The bar stays sticky at every size — only its height gives way. */
/* Only the bar's own height gives way on a short viewport. A type-and-spacing
   squeeze was tried here too and removed: it was compensating for a 632px-tall
   viewport at 150% display scaling, and at 125% (760px) it undersized a page
   that had the room to breathe. Display scaling is the user's lever for that,
   not the stylesheet's. */
@media(max-height:820px){
  :root{--nav-h:61px}
  nav{padding-block:8px}
  nav a,.nav-links a,.nav-links a.nav-cta{min-height:44px}
  .navlogo{height:30px}
}

/* ── SECTION SHELLS ────────────────────────────────────────
   One horizontal padding.

   The query container lives on the SHELL, not on .inner. An element cannot
   query a container it establishes itself, and the builder emits layout classes
   on .inner (`<div class="inner lay-split">`), so a container on .inner would
   never match its own query — every split would silently render stacked.

   container-type:inline-size measures the CONTENT box, so a shell's query size
   already excludes --gutter and equals .inner's width below the 1200px cap.
   That is why the 46rem threshold needs no gutter compensation. */
/* Sections are the unit a reader pages through, so a page-down should land on
   one rather than halfway into it. `proximity` snaps only when the scroll ends
   near a boundary, which leaves a section taller than the viewport free to be
   scrolled through normally — `mandatory` would trap its lower half. */
html{scroll-behavior:smooth;scroll-snap-type:y proximity}
.sec,.cta-sec,.band-sec{scroll-snap-align:start;scroll-margin-top:var(--nav-h)}

.sec{padding:var(--section-y) var(--gutter);background:var(--bg);container-type:inline-size}
.inner{max-width:75rem;margin-inline:auto}
.cta-sec{padding:var(--section-y) var(--gutter);text-align:center;container-type:inline-size;
  background:radial-gradient(80% 120% at 50% 0%,rgba(255,206,16,0.18),transparent 60%),#111114}
.cta-sec .inner{max-width:760px}
/* The 760px cap is a measure for centred copy. A split CTA is a different
   composition and needs the full width, or it can never reach two columns and
   the layout option is dead in practice. */
.cta-sec .inner.lay-split-even{max-width:75rem}
.cta-sec h2{font-size:var(--t-display);text-transform:uppercase}
.cta-sec.lay-banner{padding-block:var(--s-5)}

/* ── TYPE ──────────────────────────────────────────────────
   Body copy scales with everything else. On the hand-built page only headings
   scaled, so phone body text sat at desktop size in a third of the width. */
h1{font-size:var(--t-display);font-weight:900;line-height:1.05;letter-spacing:-0.02em;
  text-transform:uppercase;color:var(--fg);margin-top:var(--s-3)}
h2{font-size:var(--t-h2);font-weight:800;line-height:1.12;letter-spacing:-0.015em;
  color:var(--fg);margin-top:var(--s-2)}
h3{font-size:var(--t-h3);font-weight:800;line-height:1.25;color:var(--fg)}
h1,h2,h3{overflow-wrap:break-word}
.eyebrow{font-size:var(--t-label);font-weight:700;letter-spacing:0.22em;
  color:var(--accent);text-transform:uppercase;line-height:1.4}
.lead{color:var(--fg-body);font-weight:500;font-size:var(--t-lead);line-height:1.65;
  margin-top:var(--s-3);max-width:var(--measure)}
/* No flex-wrap. The span's flex base size is the whole sentence, so wrapping
   moved it to a second flex line and stranded the mark alone above it — the
   defect seen on every screen width. Without wrap the span shrinks in place
   (min-width:0) and breaks its own text, and align-items:center then keeps the
   mark centred against however many lines that takes. */
.badge-pill{display:inline-flex;align-items:center;gap:var(--s-2);
  background:var(--accent-dim);border:1px solid var(--accent-line);border-radius:var(--r-pill);
  padding:var(--s-1) var(--s-2);margin-bottom:var(--s-3);max-width:100%}
/* The shield carries a hardcoded height:17px inline style from the builder,
   which this file cannot edit, hence !important.

   Sized from the TEXT, never from the pill. align-self:stretch was tried and is
   wrong: height:auto on a 2500x2500 image makes the cross size resolve from the
   container, so the icon inflated the pill and then stretched to the pill it had
   just inflated — a 52px disc beside one 23px line. font-size is restated here
   so the em resolves against the label scale rather than the inherited body
   size, which is what produced 2.6em = 52px instead of ~34px.

   Scaling the icon up only when the text folds to two lines is not expressible
   in CSS — there is no line-count query. Shorter badge text is the fix for that,
   which is what the 48-character guide in the builder is for. */
.badge-pill>img{flex:0 0 auto;font-size:var(--t-label);height:1.5em!important;width:auto}
.badge-pill span{color:var(--accent);font-weight:700;font-size:var(--t-label);
  letter-spacing:0.1em;text-transform:uppercase;min-width:0;overflow-wrap:break-word;
  line-height:1.45;text-wrap:balance}

/* ── BUTTONS ───────────────────────────────────────────────
   min-height 44px is the tap-target floor, not a look. */
.btn,.btn-outline{display:inline-flex;align-items:center;justify-content:center;gap:var(--s-1);
  font-weight:800;font-size:var(--t-small);padding:10px var(--s-3);border-radius:var(--r-ctl);
  min-height:44px;transition:background var(--ease),border-color var(--ease),color var(--ease)}
.btn{background:var(--accent);color:var(--fg-invert)}
.btn:hover{background:var(--accent-hi);color:var(--fg-invert)}
.btn-outline{background:transparent;color:var(--fg);border:1px solid var(--line-strong);font-weight:700}
.btn-outline:hover{color:var(--fg);border-color:rgba(255,255,255,0.5)}
.btn-row{display:flex;gap:var(--s-2);flex-wrap:wrap;margin-top:var(--s-4)}

/* ── CONTENT-DRIVEN GRIDS ──────────────────────────────────
   One formula. --cols caps the count; --col-min is the width below which a
   track will not be squeezed, so the browser drops to fewer columns instead.
   This is what makes 2, 3, 5 and 7 items all work with no per-case rule. */
.grid3,.grid4,.lay-grid,[class*="lay-cols-"]{
  display:grid;gap:var(--gap);margin-top:var(--s-5);
  /* min(--col-min,100%) is load-bearing: a track minimum must never exceed the
     space available, or the grid overflows instead of dropping a column.
     Without it, --col-min:20rem overflowed a 272px container at 320px. */
  grid-template-columns:repeat(auto-fit,
    minmax(max(min(var(--col-min),100%), (100% - (var(--cols) - 1) * var(--gap)) / var(--cols)), 1fr));
}
.grid3{--cols:3}
.grid4{--cols:4;--col-min:15rem}
.lay-cols-1{--cols:1}
.lay-cols-2{--cols:2;--col-min:20rem}
.lay-cols-3{--cols:3;--col-min:17rem}
.lay-cols-4{--cols:4;--col-min:15rem}
/* A four-across row that cannot fit four should break to 2+2, never 3+1 — an
   orphan alone in the last row reads as a mistake and leaves a wide dead gap
   beside it. The auto-fit formula on its own fits three 15rem tracks anywhere
   in the 48–65rem band, so that band states --cols:2 explicitly. Above 65rem
   four even tracks clear --col-min and the formula produces four unaided. */
@container (max-width:65rem){
  .grid4,.lay-cols-4{--cols:2}
}

.card{border:1px solid var(--line);border-radius:var(--r-card);
  padding:var(--s-3);background:var(--bg-card)}
.card.has-img{padding:0;overflow:hidden}
.card.has-img>img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block}
.card.has-img>.ss{width:100%;border-radius:0}
.card.has-img .ss-slide{aspect-ratio:4/3;object-fit:cover}
.card.has-img>.cardbody{padding:var(--s-3)}
.card p,.step-row p,.split-item p{color:var(--fg-body);font-weight:500;font-size:var(--t-body);
  line-height:1.6;margin-top:var(--s-1);max-width:var(--measure)}
.grid3 p,.grid4 p,.icard p{min-height:calc(var(--t-body)*1.6*2)}

/* ── SPLITS ────────────────────────────────────────────────
   Derived from the measure requirement, not from a viewport guess.

   --split-min is the narrowest a text column may be: 34rem ≈ 44 characters at
   the lead size, measured in Montserrat (average advance 0.67em — a wide
   geometric sans, which is why a 458px column holds 36 characters, not 44).

   It was 35rem, which needed 2×35 + 3.5 = 73.5rem of layout box for two
   columns. .inner caps at 75rem, so two columns required a viewport of roughly
   1288px, and every narrower screen stacked the whole page at once — including
   1280×800, which missed by 8px.

   34rem is the largest value that still admits a 1280px viewport: .inner is
   1168px there, and two 34rem tracks plus the gap need 1144px. It is also the
   smallest value that keeps ONE column at 1440px with a 20px root font, where
   two tracks would need 1416px of the 1328px available — 31rem allowed two
   columns in that case and dropped the lead to ~36 characters per line, failing
   the measure floor for anyone browsing at an enlarged default size. Both
   bounds are load-bearing; this value is the only rem step that satisfies them
   together, so do not widen or narrow it without re-deriving both.

   auto-fit then produces two columns only when two such tracks plus the gap
   actually fit, and one column otherwise. No container query, deliberately:
   the CTA caps .inner at 760px while its section measures 1328px, so a query
   on the section would report room that the layout does not have. auto-fit
   measures the box the layout actually occupies. */
.lay-split,.lay-split-tight,.lay-split-even,.lay-split-wide{
  --split-min:34rem;--split-gap:3.5rem;
  display:grid;gap:var(--split-gap);align-items:center;
  grid-template-columns:repeat(auto-fit,minmax(min(var(--split-min),100%),1fr));
}
/* The HERO composes at a far narrower width than a body section does: a short
   headline and two lines of lead, not a paragraph. Body sections keep 34rem,
   which is what the measure floor requires of running text; the hero drops to
   20rem so text-left/image-right survives on a small laptop instead of
   collapsing to a stacked phone layout on a 1920px panel.

   Selected by :has(h1) because the hero is the only section type the builder
   gives an h1, and the builder's own markup cannot be changed from here — the
   admin that emits it is served from inside the login function. */
.lay-split:has(h1),
.lay-split-even:has(h1),.lay-split-wide:has(h1){--split-min:20rem}
/* .lay-split-tight is the feature section's own class — never reused for a
   no-image variant the way .lay-split/.lay-split-even are — so it always
   carries a photo plus short bio copy, the same composition as the hero.
   It gets the hero's narrower floor unconditionally instead of gated behind
   :has(h1), so a bio-with-photo section stops collapsing to stacked on a
   tablet at the same width the hero already survives on. */
.lay-split-tight{--split-min:20rem}
.lay-split-wide{align-items:start}
/* Media leads only while the split is genuinely two-column — achieved without
   any width threshold.

   direction:rtl reverses COLUMN order in a two-column grid, placing the second
   child (the media) on the left, and has no effect on vertical order when the
   grid has collapsed to one column. Children are reset to ltr so no text,
   alignment or logical property is affected.
   
   Every threshold-based version of this rule desynchronised from the grid: the
   grid switches on 35rem of layout box, while a media query in rem resolves
   against the browser default and ignores html{font-size} — so the two used
   different bases and the image was hoisted above the headline while the layout
   was still one column. This construction cannot desync because it asks no
   question about width.
   
   .lay-stacked keeps order:-1: the "Image above" layout wants media first at
   every width, which is a vertical-order intent, not a column-order one. */
.lay-stacked.lay-media-first>.lay-media{order:-1}
.lay-split.lay-media-first,.lay-split-tight.lay-media-first,
.lay-split-even.lay-media-first,.lay-split-wide.lay-media-first{direction:rtl}
.lay-split.lay-media-first>*,.lay-split-tight.lay-media-first>*,
.lay-split-even.lay-media-first>*,.lay-split-wide.lay-media-first>*{direction:ltr}
.lay-stacked{display:grid;gap:var(--s-4)}
.lay-narrow{max-width:900px}
.lay-center{text-align:center}
.lay-center .lead{margin-inline:auto}
.lay-center .btn-row{justify-content:center}
.lay-left{text-align:left}
.lay-left .lead{margin-inline:0}
.lay-left .btn-row{justify-content:flex-start}
/* No `.lay-media img{max-width:100%}` here. It scored (0,1,1) and beat the
   (0,1,0) cap on .heroimg/.galimg, so the 34rem limit silently did not apply to
   the split media it was written for — the hero and profile photos. The global
   `img{max-width:100%}` already covers this case at (0,0,1), which the cap
   correctly outranks. */

/* ── HEX MOTIF, STEPS, SPLIT LIST ──────────────────────────*/
.hex{display:block;width:26px;height:29px;flex:0 0 auto;margin-bottom:var(--s-2);
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);background:var(--accent)}
.hex-num{width:52px;height:58px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
  background:var(--accent);color:var(--fg-invert);font-weight:900;font-size:var(--t-h3)}
.steps{display:flex;flex-direction:column;gap:var(--s-3);margin-top:var(--s-5)}
.step-row{display:flex;gap:var(--s-3);align-items:flex-start}
.split-list{display:flex;flex-direction:column;gap:var(--s-2);margin-top:var(--s-4)}
.split-item{display:flex;gap:var(--s-2);align-items:flex-start}
/* A flex child defaults to min-width:auto and will not shrink below its
   min-content width, escaping the row and painting over the next column. */
.step-row>div,.split-item>div{min-width:0}
.step-row h3,.split-item h3{overflow-wrap:break-word}

/* ── STATEMENT BAND ────────────────────────────────────────*/
.band-sec{padding:var(--section-y) var(--gutter);text-align:center;container-type:inline-size;
  background:var(--bg) url(data:image/svg+xml,%3Csvg%20width=%2228%22%20height=%2249%22%20viewBox=%220%200%2028%2049%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cg%20fill=%22none%22%20fill-rule=%22evenodd%22%3E%3Cg%20fill=%22%23ffce10%22%20fill-opacity=%220.05%22%3E%3Cpath%20d=%22M13.99%209.25l13%207.5v15l-13%207.5L1%2031.75v-15l12.99-7.5zM3%2017.9v12.7l10.99%206.34%2011-6.35V17.9l-11-6.34L3%2017.9zM0%2015l12.98-7.5V0h-2v6.35L0%2012.69v2.3zm0%2018.5L12.98%2041v8h-2v-6.85L0%2035.81v-2.3zM15%200v7.5L27.99%2015H28v-2.31h-.01L17%206.35V0h-2zm0%2049v-8l12.99-7.5H28v2.31h-.01L17%2042.15V49h-2z%22/%3E%3C/g%3E%3C/g%3E%3C/svg%3E)}
.band-sec.band-tight{padding-block:var(--s-6)}
.band-mark{height:56px;width:auto;margin:0 auto var(--s-3);display:block}
.band-lead{color:var(--fg);font-size:var(--t-h2);line-height:1.3;font-weight:700;
  margin-inline:auto;max-width:38ch}
.band-quote{color:var(--fg-body);font-weight:500;font-size:var(--t-body);font-style:italic;
  line-height:1.6;margin:var(--s-3) auto 0;max-width:52ch}

/* ── MEDIA ─────────────────────────────────────────────────*/
/* NEVER crop these. cover was cutting the top off a portrait — a photograph of
   a person losing its head is worse than one that does not fill its box. contain
   fits the whole frame inside the cap and centres it, so a tall image shows
   complete rather than cropped.

   ONE constraint only. Two are what caused every version of this bug:

     object-fit:cover + max-height  -> cropped the top off a portrait
     width:100% + max-height + contain -> letterboxed inside an over-wide box,
       and --r-media rounded the empty container instead of the photo
     width:auto + max-width + max-height -> the two maxima clamped independently
       and STRETCHED a square photo to 570x456

   Width drives the size and height follows from the image's own ratio, so a
   square photo is square, nothing is cropped, nothing is letterboxed, and
   distortion is not expressible. max-width (not max-height) is what stops one
   photo swallowing a short viewport: in a two-column split the column is
   narrower than the cap anyway, and in a stacked layout the cap holds a square
   image to 34rem instead of the full 1200px content width. */
.heroimg,.galimg{display:block;width:100%;height:auto;max-width:34rem;
  margin-inline:auto;border-radius:var(--r-media)}
.pgrid{display:grid;gap:var(--s-2);margin-top:var(--s-4);
  grid-template-columns:repeat(auto-fit,minmax(min(15rem,100%),1fr))}
.pgrid img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-media);
  display:block;border:1px solid var(--line-mid)}
.vwrap{position:relative;aspect-ratio:16/9;overflow:hidden;border-radius:var(--r-media);margin-block:var(--s-3)}
.vwrap iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vlink{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2);background:var(--accent-dim);
  border:1px solid var(--accent-line);border-radius:var(--r-ctl);color:var(--fg);
  margin-block:var(--s-2);font-weight:600;font-size:var(--t-small);min-height:44px}
.vlink img{width:96px;height:60px;object-fit:cover;border-radius:6px;flex-shrink:0}
/* (The 4/3 container override is gone — it was forcing a crop ratio onto
   images whose own ratio is the thing worth keeping.) */

/* ── SLIDESHOW ─────────────────────────────────────────────
   Auto-advance is pausable (WCAG 2.2.2) and skipped under reduced motion. */
.ss{position:relative;overflow:hidden;border-radius:var(--r-media);border:1px solid var(--line-mid)}
.ss-track{position:relative;display:grid}
.ss-slide{grid-area:1/1;width:100%;display:block;opacity:0;transition:opacity .5s ease}
.ss-slide.on{opacity:1}
.ss-arrow,.ss-play{position:absolute;width:48px;height:48px;border-radius:50%;
  border:1px solid rgba(255,255,255,.4);background:rgba(11,11,13,.74);color:var(--fg);
  display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;
  font-family:inherit;transition:opacity var(--ease),background var(--ease),color var(--ease)}
.ss-arrow{top:50%;transform:translateY(-50%);font-size:27px;line-height:1}
.ss-prev{left:12px}.ss-next{right:12px}
.ss-play{bottom:12px;right:12px;font-size:13px}
.ss:hover .ss-arrow,.ss:focus-within .ss-arrow,.ss:hover .ss-play,.ss:focus-within .ss-play{opacity:1}
.ss-arrow:hover,.ss-play:hover{background:var(--accent);color:var(--fg-invert);border-color:var(--accent)}
.ss-arrow:focus-visible,.ss-play:focus-visible{opacity:1}
.ss-status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
@media(hover:none){.ss-arrow,.ss-play{opacity:.92}}

/* ── INTERACTIVE CARDS + MODAL ─────────────────────────────*/
.icard{display:block;width:100%;text-align:left;font-family:inherit;cursor:pointer;color:var(--fg);
  transition:border-color .18s ease,transform .18s ease}
.icard:hover{border-color:var(--accent-line);transform:translateY(-2px)}
.icard.has-img{padding:0;overflow:hidden}
.ic-more{display:inline-block;margin-top:var(--s-2);color:var(--accent);font-weight:700;font-size:var(--t-small)}
.ic-ov{position:fixed;inset:0;z-index:2000;background:rgba(5,5,6,0.92);display:flex;
  align-items:flex-start;justify-content:center;padding:var(--s-3);overflow:auto}
.ic-box{--ic-pad:var(--s-4);--ic-close-size:44px;--ic-close-inset:14px;
  position:relative;width:100%;max-width:900px;margin:auto;background:var(--bg-alt);
  border:1px solid var(--line-mid);border-radius:var(--r-card);overflow:hidden;
  box-shadow:0 40px 120px rgba(0,0,0,0.7)}
.ic-close{position:absolute;top:var(--ic-close-inset);right:var(--ic-close-inset);z-index:3;
  width:var(--ic-close-size);height:var(--ic-close-size);border-radius:50%;
  background:rgba(0,0,0,0.55);border:none;color:var(--fg);font-size:24px;line-height:1;
  cursor:pointer;font-family:inherit}
.ic-media{position:relative;width:100%;aspect-ratio:16/9;background:#000;overflow:hidden}
.ic-media iframe,.ic-media img{position:absolute;inset:0;width:100%;height:100%;border:0;object-fit:cover}
.ic-txt{padding:var(--s-4) var(--ic-pad)}
/* Clearance derived from the button's own size and inset so the two cannot
   drift apart, and break-word so an unbreakable title cannot overflow past it. */
.ic-txt h3{font-size:var(--t-h3);line-height:1.25;
  padding-right:max(0px,calc(var(--ic-close-inset) + var(--ic-close-size) + 8px - var(--ic-pad)))}
.ic-txt p{color:var(--fg-body);font-size:var(--t-body);line-height:1.65;
  margin-top:var(--s-2);max-width:var(--measure)}
.ic-part{margin-top:var(--s-3)}
.ic-part p{color:#d0d0d8;font-weight:500;font-size:var(--t-body);line-height:1.6;margin:0;max-width:var(--measure)}
.ic-part p.ic-part-lbl{font-size:var(--t-label);font-weight:700;letter-spacing:0.16em;
  color:var(--accent);text-transform:uppercase;margin-bottom:6px;line-height:1.3}

/* ── ACCORDION ─────────────────────────────────────────────*/
.iacc-list{margin-top:var(--s-5)}
.iacc{border:1px solid var(--line);border-radius:var(--r-ctl);background:var(--bg-card);
  margin-bottom:var(--s-2);overflow:hidden}
.iacc summary{padding:var(--s-3);cursor:pointer;list-style:none;display:flex;
  align-items:flex-start;gap:var(--s-2);min-height:44px}
.iacc summary::-webkit-details-marker{display:none}
.iacc summary::after{content:'+';margin-left:auto;color:var(--accent);font-weight:800;font-size:22px;line-height:1}
.iacc[open] summary::after{content:'–'}
.iacc summary p{color:var(--fg-body);font-size:var(--t-body);line-height:1.6;margin-top:4px;max-width:var(--measure)}
.iacc-d{padding:0 var(--s-3) var(--s-3) 62px;color:var(--fg-body);font-size:var(--t-body);
  line-height:1.65;max-width:var(--measure)}

/* ── FOOTER ────────────────────────────────────────────────*/
footer{padding:var(--s-5) var(--gutter);background:var(--bg-deep);border-top:1px solid var(--line);
  display:flex;flex-direction:column;gap:var(--s-3)}
.foot-top{display:grid;gap:var(--s-3);align-items:center;
  grid-template-columns:repeat(auto-fit,minmax(min(14rem,100%),1fr))}
.foot-logo{height:38px;width:90px;object-fit:contain;opacity:.9;justify-self:start}
.fsocial{display:flex;align-items:center;gap:var(--s-1);padding:9px 18px 9px 12px;
  border-radius:var(--r-pill);background:#969696;color:var(--fg-invert);font-weight:800;
  font-size:var(--t-small);min-height:44px;justify-self:center;
  box-shadow:0 6px 18px rgba(255,206,16,0.25);transition:transform var(--ease),box-shadow var(--ease)}
.fsocial:hover{color:var(--fg-invert);transform:translateY(-1px);box-shadow:0 8px 22px rgba(255,206,16,0.4)}
.foot-copy{color:var(--fg-muted);font-size:var(--t-small);justify-self:end;text-align:right}
.foot-copy a{color:var(--fg-muted);font-weight:600}
.flegal{display:flex;gap:var(--s-3);flex-wrap:wrap;align-items:center;justify-content:center}
.flegal a{color:var(--fg-muted);font-weight:500;font-size:var(--t-small);display:inline-flex;align-items:center;min-height:44px}
footer .flinks{display:flex;gap:var(--s-3);flex-wrap:wrap}
footer .flinks a{color:var(--fg-body);font-weight:500;font-size:var(--t-small);display:inline-flex;align-items:center;min-height:44px}
footer p{color:var(--fg-muted);font-size:var(--t-small)}
/* Footer is page-level chrome, not a component adapting to a parent — the same
   justification this file states for nav, and the reason a container query is
   wrong here: <footer> is a sibling of <main>, so it has no section shell above
   it to query. The three children's justify-self declarations are set on the
   grid axis and must each be reset, or centring the text changes nothing. */
@media(max-width:900px){
  .foot-top{grid-template-columns:1fr;justify-items:center;text-align:center}
  .foot-logo,.fsocial,.foot-copy{justify-self:center;text-align:center}
}


/* Background treatment, independent of layout and tone. The honeycomb was
   previously reachable only via .band-sec, so a split section could not carry
   the motif the hand-built homepage used. */
.sec-hex{background-image:url(data:image/svg+xml,%3Csvg%20width=%2228%22%20height=%2249%22%20viewBox=%220%200%2028%2049%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cg%20fill=%22none%22%20fill-rule=%22evenodd%22%3E%3Cg%20fill=%22%23ffce10%22%20fill-opacity=%220.05%22%3E%3Cpath%20d=%22M13.99%209.25l13%207.5v15l-13%207.5L1%2031.75v-15l12.99-7.5zM3%2017.9v12.7l10.99%206.34%2011-6.35V17.9l-11-6.34L3%2017.9zM0%2015l12.98-7.5V0h-2v6.35L0%2012.69v2.3zm0%2018.5L12.98%2041v8h-2v-6.85L0%2035.81v-2.3zM15%200v7.5L27.99%2015H28v-2.31h-.01L17%206.35V0h-2zm0%2049v-8l12.99-7.5H28v2.31h-.01L17%2042.15V49h-2z%22/%3E%3C/g%3E%3C/g%3E%3C/svg%3E)}
/* Case tag: sector and audience, above the title on card and modal. */
/* Must out-specify `.card p` and `.ic-txt p`, which are (0,1,1) and would
   otherwise set this label to body size and colour. Same fault as .ic-part-lbl. */
.ic-tag,.card p.ic-tag,.icard p.ic-tag,.ic-txt p.ic-tag{font-size:var(--t-label);font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--fg-muted);line-height:1.3;margin:0 0 var(--s-1);max-width:none}
/* The close button is positioned against .ic-box, and .ic-tag renders ABOVE the
   h3 in the modal, so the button sat on top of the tag text — 26x21px of measured
   overlap on "Manufacturing". Reuses .ic-txt h3's expression rather than a fixed
   value so the two cannot drift apart from --ic-close-inset/--ic-close-size. */
.ic-txt p.ic-tag{margin-bottom:6px;
  padding-right:max(0px,calc(var(--ic-close-inset) + var(--ic-close-size) + 8px - var(--ic-pad)))}

/* ── ENTRANCE ANIMATION ────────────────────────────────────*/
[data-anim]{opacity:0;transition:opacity .7s ease,transform .7s ease}
[data-anim="fade-up"]{transform:translateY(30px)}
[data-anim="slide-left"]{transform:translateX(-40px)}
[data-anim="slide-right"]{transform:translateX(40px)}
[data-anim="zoom-in"]{transform:scale(.92)}
[data-anim].vis{opacity:1;transform:none}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;scroll-snap-type:none}
  [data-anim]{opacity:1;transform:none;transition:none}
  .ss-slide{transition:none}
  .icard,.btn,.btn-outline,.fsocial{transition:none}
}

