/* ============================================================
   All You Need Rental — "Canvas & Lawn" design system
   DNA hash c7a41e0d93b6 · see design-dna.yml

   Every value below is an ERS theme-override surface: drop this
   :root block into an Event Rental Systems custom stylesheet and
   the storefront inherits the whole system.
   ============================================================ */

:root {
  /* ---- colour -------------------------------------------- */
  --canvas:   #F4EDDF;   /* page base, warm cream            */
  --paper:    #FCF8EF;   /* card surface                     */
  --ink:      #16342A;   /* spruce-black, all body text      */
  --pine:     #234C3B;   /* dark bands                       */
  --lawn:     #3E7A5C;   /* rules, icons, large labels ONLY  */
  --marigold: #F2A81C;   /* primary CTA fill                 */
  --clay:     #C2472A;   /* graduation urgency               */
  --sage:     #C3D2C2;   /* wedding tonal fills              */
  --bark:     #6E6355;   /* muted body text (5.04:1)         */

  /* ---- type ---------------------------------------------- */
  --display: 'Bricolage Grotesque', 'Trebuchet MS', sans-serif;
  --body:    'Hanken Grotesk', system-ui, sans-serif;
  --editorial: 'Faustina', Georgia, serif;

  --t--1: .82rem;  --t-0: 1rem;    --t-1: 1.26rem;  --t-2: 1.59rem;
  --t-3: 2rem;     --t-4: 2.52rem; --t-5: 3.18rem;  --t-6: 4rem;
  --t-7: 5.05rem;

  /* ---- structure ----------------------------------------- */
  --wrap: 1240px;
  --gutter: 24px;
  --band: 104px;          /* space between horizon bands     */
  --gable: 34px;          /* the peak, at card scale         */
  --scallop: 15px;        /* valance radius                  */
  --nav-h: 104px;

  /* ---- shadows, varied by purpose ------------------------ */
  --sh-nav:  0 1px 0 rgba(22,52,42,.10);
  --sh-card: 0 10px 28px -18px rgba(22,52,42,.45);
  --sh-lift: 0 18px 40px -22px rgba(22,52,42,.55);

  --ease-cloth: cubic-bezier(.22,.9,.24,1);
  /* The flap draw: one curve, no bounce. Kept as a token for reference, but
     the keyframes must inline it: var() does not resolve for
     animation-timing-function inside a keyframe, and the draw silently ran
     linear until it was written out longhand. */
  --ease-draw:  cubic-bezier(.48,.02,.16,1);
}

/* ============================================================
   Base reset. Tailwind's Play CDN injects preflight AFTER any
   stylesheet, which resets h1..h6 to inherit and flattens the
   whole type scale, so preflight is disabled in the config on
   every page and this stands in for it.
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;              /* clip, not hidden — hidden breaks sticky */
}
img, svg, video { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--display);
  font-weight: 800;
  font-variation-settings: 'wdth' 92;
  line-height: .96;
  letter-spacing: -.022em;
  margin: 0;
  text-wrap: balance;
}
p { margin: 0 0 1em; }
ul, ol { margin: 0 0 1em; padding-left: 1.15em; }
:focus-visible { outline: 3px solid var(--marigold); outline-offset: 3px; border-radius: 2px; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-narrow { max-width: 760px; }

/* ============================================================
   The gable. A shallow peak clipped off the top edge, used at
   badge, card and band scale. Same angle every time.
   ============================================================ */
.gable { clip-path: polygon(0 var(--gable), 50% 0, 100% var(--gable), 100% 100%, 0 100%); }
.gable-sm { --gable: 14px; }
.gable-lg { --gable: 64px; }

/* ============================================================
   The valance. Real tents are hemmed with a scalloped edge, and
   it is the only horizontal divider in this system — there is
   not one straight rule anywhere.
   ============================================================ */
.valance {
  height: var(--scallop);
  background: var(--valance-bg, var(--canvas));
  -webkit-mask: radial-gradient(circle var(--scallop) at 50% 0, #000 98%, transparent 100%) repeat-x;
          mask: radial-gradient(circle var(--scallop) at 50% 0, #000 98%, transparent 100%) repeat-x;
  -webkit-mask-size: calc(var(--scallop) * 2) 100%;
          mask-size: calc(var(--scallop) * 2) 100%;
  pointer-events: none;
}
.valance-up { transform: scaleY(-1); }

/* A guy line: the taut hairline that anchors a tent. Used as the
   eyebrow rule above section headings. */
.guyline {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--body); font-weight: 600;
  font-size: var(--t--1); letter-spacing: .17em; text-transform: uppercase;
  color: var(--lawn); margin-bottom: 18px;
}
.guyline::before { content: ''; width: 34px; height: 2px; background: currentColor; flex: none; }
.guyline.on-dark { color: var(--sage); }

/* ============================================================
   Bands
   ============================================================ */
.band { padding-block: var(--band); position: relative; }
.band-tight { --band: 64px; }
.band-airy  { --band: 136px; }
.band-paper { background: var(--paper); }
.band-pine  { background: var(--pine); color: var(--canvas); }
.band-ink   { background: var(--ink); color: var(--canvas); }
.band-pine :is(h1,h2,h3,h4), .band-ink :is(h1,h2,h3,h4) { color: var(--canvas); }

/* A light surface sitting on a dark band keeps its own ink. Without this the
   band's colour is inherited straight through a card and the copy inside it
   goes cream-on-cream. */
.band-pine :is(.card,.quote,.datebar,.map-card),
.band-ink  :is(.card,.quote,.datebar,.map-card) { color: var(--ink); }
.band-pine :is(.card,.quote,.datebar,.map-card) :is(h1,h2,h3,h4),
.band-ink  :is(.card,.quote,.datebar,.map-card) :is(h1,h2,h3,h4) { color: var(--ink); }

/* A plain weave: warp and weft with the over-under of real canvas, plus slub
   and fibre noise. Storytelling bands only, and kept near the threshold of
   visibility. (Lifting the texture off the client's photograph was tried
   first and abandoned: the tent's guy lines are thin, high-contrast features
   that survive any high-pass and tiled into a visible chevron lattice.) */
.weave { position: relative; isolation: isolate; }
.weave::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: url('img/canvas-weave.jpg');
  background-size: 150px;
  opacity: .5;
  mix-blend-mode: multiply;
}
.band-pine.weave::before, .band-ink.weave::before { opacity: .85; mix-blend-mode: soft-light; }

/* ============================================================
   Buttons — deliberate mixing: gabled containers, pill buttons.
   Pressable, so they translate rather than casting a shadow.
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55em;
  min-height: 52px; padding: 0 30px;
  border-radius: 999px; border: 0;
  font-family: var(--body); font-weight: 700; font-size: 1.02rem;
  letter-spacing: .005em; text-decoration: none; cursor: pointer;
  transition: transform .16s var(--ease-cloth), background-color .16s, border-color .16s;
}
.btn:active { transform: translateY(2px); }
.btn-primary { background: var(--marigold); color: var(--ink); }
.btn-primary:hover { background: #FFBB33; }
.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); }
.btn-ghost:hover { background: rgba(22,52,42,.06); }
.btn-ghost.on-dark { color: var(--canvas); box-shadow: inset 0 0 0 1.5px rgba(244,237,223,.55); }
.btn-ghost.on-dark:hover { background: rgba(244,237,223,.10); }
.btn-sm { min-height: 46px; padding: 0 20px; font-size: .95rem; }
.btn-clay { background: var(--clay); color: var(--paper); }
.btn-clay:hover { background: #D6512F; }

.tlink {
  font-weight: 600; color: var(--lawn); text-decoration: underline;
  text-decoration-thickness: 2px; text-underline-offset: 4px;
}
.tlink.on-dark { color: var(--marigold); }

/* ============================================================
   Navigation — the eave. Its bottom edge is hemmed with the same
   scallop as the section seams, so the bar reads as the eave of
   the tent you are standing under.
   ============================================================ */
.eavebar {
  position: sticky; top: 0; z-index: 60;
  background: var(--canvas); box-shadow: var(--sh-nav);
}
.eavebar::after {
  content: ''; position: absolute; left: 0; right: 0; top: 100%;
  height: var(--scallop); background: var(--canvas);
  -webkit-mask: radial-gradient(circle var(--scallop) at 50% 0, #000 98%, transparent 100%) repeat-x;
          mask: radial-gradient(circle var(--scallop) at 50% 0, #000 98%, transparent 100%) repeat-x;
  -webkit-mask-size: calc(var(--scallop) * 2) 100%;
          mask-size: calc(var(--scallop) * 2) 100%;
  pointer-events: none;
}
.eave-inner {
  display: flex; align-items: center; gap: 18px;
  min-height: var(--nav-h);
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; flex: none; }
.brand img { height: 84px; width: auto; }
.navlinks { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.navlink {
  position: relative; display: inline-flex; align-items: center;
  min-height: 44px; padding: 0 13px; border-radius: 999px;
  font-weight: 600; font-size: .96rem; text-decoration: none; white-space: nowrap;
  transition: background-color .15s;
}
.navlink:hover { background: rgba(22,52,42,.07); }
.navlink[aria-current="page"] { color: var(--lawn); }
.navlink[aria-current="page"]::after {
  content: ''; position: absolute; left: 13px; right: 13px; bottom: 12px;
  height: 2px; background: var(--marigold);
}
.navtel {
  display: inline-flex; align-items: center; gap: 7px; min-height: 44px;
  padding: 0 12px; font-family: var(--display); font-weight: 700;
  font-size: 1.02rem; text-decoration: none; white-space: nowrap;
}

/* All Products mega-panel */
.mega-wrap { position: relative; }
.mega {
  position: absolute; top: calc(100% + var(--scallop) + 2px); left: 50%;
  transform: translateX(-50%) translateY(-6px);
  width: min(760px, calc(100vw - 32px));
  background: var(--pine); color: var(--canvas);
  padding: 26px 28px 28px; z-index: 70;
  box-shadow: var(--sh-lift);
  opacity: 0; visibility: hidden;
  transition: opacity .18s, transform .18s var(--ease-cloth), visibility .18s;
}
.mega[data-open="true"] { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
.mega-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 26px; }
.mega a {
  display: block; padding: 9px 10px; border-radius: 6px;
  text-decoration: none; font-weight: 600; font-size: .97rem;
  color: var(--canvas);
}
.mega a:hover { background: rgba(244,237,223,.12); }
.mega-head {
  font-family: var(--display); font-size: var(--t--1); font-weight: 700;
  letter-spacing: .17em; text-transform: uppercase; color: var(--sage);
  margin-bottom: 10px;
}

.navtoggle { display: none; }

/* Mobile sheet */
.sheet {
  position: fixed; inset: 0; z-index: 90; background: var(--pine); color: var(--canvas);
  padding: 22px var(--gutter) 130px; overflow-y: auto;
  transform: translateY(-100%); transition: transform .3s var(--ease-cloth);
}
.sheet[data-open="true"] { transform: translateY(0); }
.sheet a { display: block; text-decoration: none; }
.sheet .sheet-primary {
  font-family: var(--display); font-weight: 800; font-size: var(--t-2);
  padding: 11px 0; border-bottom: 1px solid rgba(244,237,223,.16);
}
.sheet .sheet-sub { padding: 9px 0 9px 14px; font-weight: 600; opacity: .88; }

/* Mobile call bar — majority of party-rental traffic is a phone */
.callbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
  display: none; gap: 10px; padding: 10px var(--gutter) calc(10px + env(safe-area-inset-bottom));
  background: var(--ink); box-shadow: 0 -6px 20px -12px rgba(0,0,0,.6);
}
.callbar .btn { flex: 1; min-height: 50px; padding: 0 12px; font-size: .97rem; }

/* ============================================================
   Cards
   ============================================================ */
.card {
  background: var(--paper); box-shadow: var(--sh-card);
  border-radius: 0 0 4px 4px; overflow: hidden;
  display: flex; flex-direction: column;
  transition: transform .22s var(--ease-cloth), box-shadow .22s;
}
.card-media { position: relative; overflow: hidden; background: var(--sage); }
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease-cloth); }

/* Two visual registers, deliberately.
   Occasion tiles carry a PHOTOGRAPH of a real event, edge to edge.
   Catalog tiles carry a cut-out of the actual item, floated on a sage swatch
   with air around it. The client's catalogue shots are white-background
   cut-outs: a white tablecloth on a white card is invisible, and cropping
   them like photographs is what makes a rental site look like a spreadsheet.
   On a swatch they read as the item itself, which is what is being rented. */
.card-media.swatch {
  background:
    radial-gradient(120% 92% at 50% 6%, rgba(255,255,255,.72), transparent 62%),
    var(--sage);
  padding: 12% 13% 11%;
}
.card-media.swatch img { object-fit: contain; filter: drop-shadow(0 10px 14px rgba(22,52,42,.20)); }
a.card:hover .card-media.swatch img { transform: scale(1.055) translateY(-3px); }

/* A scale drawing instead of a photograph. Nine cards carrying the same
   product shot say nothing; nine plans drawn to one shared scale say
   exactly how much bigger each tent is and how many tables fit under it. */
.card-media.plan {
  background:
    linear-gradient(rgba(22,52,42,.055) 1px, transparent 1px) 0 0 / 100% 14px,
    linear-gradient(90deg, rgba(22,52,42,.055) 1px, transparent 1px) 0 0 / 14px 100%,
    var(--paper);
  padding: 16px 18px;
}

/* Where no photograph of the real item exists, the tile says so in type
   rather than showing a picture of something else. */
.card-media.tile-type {
  display: grid; place-items: center; text-align: center;
  background: var(--sage); padding: 16px;
}
.card-media.tile-type span {
  font-family: var(--display); font-weight: 800; font-size: var(--t-2);
  font-variation-settings: 'wdth' 88; line-height: 1.02; color: var(--ink);
}
.card-body { padding: 18px 20px 22px; display: flex; flex-direction: column; flex: 1; }
.card-name { font-size: var(--t-1); line-height: 1.02; }
a.card:hover, .card:hover { transform: translateY(-5px); box-shadow: var(--sh-lift); }
a.card:hover .card-media img { transform: scale(1.045); }
a.card { text-decoration: none; color: inherit; }

/* The one playful exception in the whole system: inflatables and
   games get a two-bounce hover. Nothing else does. */
@media (hover: hover) {
  a.card.bouncy:hover { animation: bounce-2 .62s var(--ease-cloth); }
}
@keyframes bounce-2 {
  0%   { transform: translateY(-5px); }
  30%  { transform: translateY(-16px); }
  55%  { transform: translateY(-5px); }
  76%  { transform: translateY(-11px); }
  100% { transform: translateY(-5px); }
}

.price { font-family: var(--display); font-weight: 800; font-size: var(--t-1); }
.price small { font-family: var(--body); font-weight: 500; font-size: .72rem; color: var(--bark); letter-spacing: .04em; }

.flag {
  position: absolute; top: calc(var(--gable) + 6px); left: 12px; z-index: 2;
  display: inline-flex; align-items: center; height: 27px; padding: 0 11px;
  background: var(--marigold); color: var(--ink);
  font-family: var(--display); font-weight: 700; font-size: .74rem;
  letter-spacing: .12em; text-transform: uppercase;
}
.flag-clay { background: var(--clay); color: var(--paper); }
.flag-pine { background: var(--pine); color: var(--canvas); }

/* ============================================================
   The category mosaic. Deliberately unequal: two hero tiles, then
   mid tiles, then small ones. A grid of identical tiles is the
   thing the current site already does and the thing to avoid.
   ============================================================ */
.mosaic { display: grid; grid-template-columns: repeat(6, 1fr); gap: 18px; }
.m-hero  { grid-column: span 3; }
.m-hero { --gable: 26px; }
.m-hero .card-media { aspect-ratio: 16/10; }
.m-hero .card-name { font-size: var(--t-3); }
.m-mid   { grid-column: span 2; }
.m-mid .card-media { aspect-ratio: 4/3; }
.m-mid .card-name { font-size: var(--t-2); }
.m-small { grid-column: span 2; }
.m-small .card-media { aspect-ratio: 3/2; }
.m-wide  { grid-column: span 3; }
.m-wide .card-media { aspect-ratio: 2/1; }
.m-wide .card-name { font-size: var(--t-2); }

/* The closing strip. Runs the full six columns and lays out sideways, which
   is what stops the mosaic resolving into a tidy waffle at the bottom. */
.m-strip { grid-column: span 6; flex-direction: row; align-items: stretch; }
.m-strip .card-media { flex: 0 0 34%; aspect-ratio: auto; }
.m-strip .card-body { justify-content: center; padding: 26px 30px; }
.m-strip .card-name { font-size: var(--t-2); }

@media (max-width: 900px) {
  .mosaic { grid-template-columns: repeat(4, 1fr); }
  .m-hero { grid-column: span 4; }
  .m-mid, .m-small { grid-column: span 2; }
  .m-wide { grid-column: span 2; }
  .m-wide .card-media { aspect-ratio: 16/9; }
  .m-strip { grid-column: span 4; }
}
@media (max-width: 560px) {
  .mosaic { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .m-hero { grid-column: span 2; }
  .m-mid, .m-small, .m-wide { grid-column: span 1; }
  .m-hero .card-name { font-size: var(--t-2); }
  .m-mid .card-name, .m-small .card-name, .m-wide .card-name { font-size: 1.05rem; }
  .m-strip { grid-column: span 2; flex-direction: column; }
  .m-strip .card-media { flex: none; aspect-ratio: 2/1; }
  .m-strip .card-body { padding: 18px 20px 22px; }
}

/* ============================================================
   HERO — "Walk Into the Tent"
   Default state below is the OPEN tent. If JavaScript never runs
   the visitor gets a correct, complete hero; the sequence is pure
   progressive enhancement layered on top by the .tent-run class.
   ============================================================ */
.hero { position: relative; overflow: hidden; background: var(--ink); isolation: isolate; }
.hero-photo { position: absolute; inset: 0; z-index: 0; }
.hero-photo img { width: 100%; height: 100%; object-fit: cover; object-position: center 42%; }
.hero-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(96deg, rgba(15,32,25,.86) 0%, rgba(15,32,25,.66) 42%, rgba(15,32,25,.18) 74%, rgba(15,32,25,.36) 100%),
    linear-gradient(0deg, rgba(15,32,25,.55) 0%, transparent 46%);
}
.hero-inner {
  position: relative; z-index: 4;
  padding-block: clamp(76px, 12vw, 150px);
  color: var(--canvas);
  max-width: 720px;
}
.hero h1 {
  font-size: clamp(2.9rem, 7.4vw, 5.05rem);
  font-variation-settings: 'wdth' 88;
  margin-bottom: 20px;
}
.hero h1 em { font-style: normal; color: var(--marigold); }
.hero-sub { font-size: clamp(1.05rem, 2.1vw, 1.26rem); max-width: 44ch; color: #EDE6D8; }

/* The flaps. They are the entrance AND the permanent framing —
   they never vanish, they park at the edges of the viewport.

   Two elements per flap, and the split is what makes the opening smooth. The
   WRAPPER carries the big slide and nothing else, so it can run as a single
   uninterrupted curve from closed to parked. The PLATE inside carries the
   cloth character, the swing and the skew.

   They were one element before. Every intermediate keyframe needed for the
   swing also chopped the slide into segments, and a timing function in CSS
   applies per segment, so the flap decelerated into and accelerated out of
   each one. Four keyframes, four stutters, which is what read as hesitation. */
.hero-frame { position: absolute; inset: 0; z-index: 3; pointer-events: none; overflow: hidden; }
.flap-wrap {
  /* Generous overscan. The plate rotates and skews as it swings, and a
     tight-fitting box opens a wedge of bare background at the top corner
     the moment it does. */
  position: absolute; top: -14%; height: 128%; width: 58%;
  will-change: transform;
}
.flap-wrap-l { left: -2%;  transform: translateX(-84%); }
.flap-wrap-r { right: -2%; transform: translateX(84%); }
.flap { width: 100%; height: 100%; object-fit: cover; will-change: transform; }
.flap-l { transform-origin: 100% 12%; }
.flap-r { transform-origin: 0 12%; }

/* The nav's own scallop already hems the top of the hero, so the hero does
   not draw a second one. */
/* The shadow the opening flaps throw. It belongs UNDER them, at z-index 2:
   above the photograph it darkens, below the canvas that is casting it. Sat
   above the flaps it painted a hard grey slab straight across the lit canvas,
   which is not a shadow, it is a wipe. Soft and shallow, because a cloth
   shadow in daylight has no hard edge and no flat middle. */
.hero-shadow {
  position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: 0;
  /* A narrow band, not a wash. Wide stops read as "the whole photograph got
     darker", which is not what a flap edge does to the ground it passes over. */
  background: linear-gradient(101deg,
    transparent 24%,
    rgba(12,28,20,.07) 35%,
    rgba(12,28,20,.24) 45%,
    rgba(12,28,20,.07) 55%,
    transparent 66%);
  /* No blur filter: a full-bleed blurred layer is a real compositing cost on
     every frame of a 2s animation, and gradient stops are free and just as
     soft. */
}

/* One control, two jobs. While the sequence runs it offers a way out; the
   rest of the time it offers a way back in, so a visitor who did not
   refresh can still watch the tent open. Hidden without JavaScript,
   because without JavaScript there is nothing to replay. */
.tent-control {
  /* Fixed and anchored under the nav, shown only while the hero is on
     screen. Absolute positioning failed both ways round: at the hero's
     bottom edge it sits below the fold exactly when it is needed, and at
     the hero's top edge it slides under the sticky nav as soon as the page
     moves a pixel. */
  position: fixed; right: 20px; top: calc(var(--nav-h) + 22px); z-index: 55;
  display: none; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 18px; border-radius: 999px;
  background: rgba(15,32,25,.66); color: #F4EDDF;
  border: 1px solid rgba(244,237,223,.42);
  font-weight: 600; font-size: .9rem; cursor: pointer;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden;
  transition: opacity .25s var(--ease-cloth), visibility .25s, background-color .16s, border-color .16s;
}
.js-ready .tent-control { display: inline-flex; }
.tent-control.is-visible { opacity: 1; visibility: visible; }
.tent-control:hover { background: rgba(15,32,25,.86); border-color: rgba(244,237,223,.72); }
.tent-control svg { flex: none; }
.tent-control .lbl-skip, .tent-control .ico-skip { display: none; }
.tent-control[data-mode="skip"] .lbl-skip, .tent-control[data-mode="skip"] .ico-skip { display: inline; }
.tent-control[data-mode="skip"] .lbl-replay, .tent-control[data-mode="skip"] .ico-replay { display: none; }

/* ---- the sequence ----------------------------------------------------
   4.3s total: the tent is held closed and simply breathing for the first
   1.9s (44% of the run) before anything opens, then the 2.4s opening.
   The hold is the point of the whole thing — you are standing outside a
   real tent for a beat before you walk into it — so the control above is
   present from the first frame and the nav sits above the flaps
   throughout, which keeps Book Now and the phone number live the entire
   time.
   --------------------------------------------------------------------- */
.tent-run .flap-wrap-l { animation: flap-slide-l 4.30s linear backwards; }
.tent-run .flap-wrap-r { animation: flap-slide-r 4.30s linear backwards; }
.tent-run .flap-l      { animation: flap-cloth-l 4.30s linear backwards; }
.tent-run .flap-r      { animation: flap-cloth-r 4.30s linear backwards; }
.tent-run .hero-photo  { animation: push-in     4.30s var(--ease-cloth) backwards; }
.tent-run .hero-shadow { animation: sweep       4.30s ease-out          backwards; }
.tent-run .hero-inner  { animation: settle-in   1.05s var(--ease-cloth) 3.25s backwards; }

/* 0 to 44.2% is the hold. The canvas is not frozen during it: it lifts and
   settles the way a tent wall does in a light breeze.

   The slide is TWO keyframes and one curve. No anticipation beat pulling the
   flap inward before it opens, no overshoot-and-settle at the end: both were
   deliberate weight cues and both read as the flap hesitating. What is left
   is one continuous draw, easing gently out of rest and landing soft.
   --ease-draw does the whole job in a single segment. */
@keyframes flap-slide-l {
  0%, 44.2% { transform: translateX(0); animation-timing-function: cubic-bezier(.48,.02,.16,1); }
  100%      { transform: translateX(-84%); }
}
@keyframes flap-slide-r {
  0%, 44.2% { transform: translateX(0); animation-timing-function: cubic-bezier(.48,.02,.16,1); }
  100%      { transform: translateX(84%); }
}

/* The cloth character rides on the plate inside. These values are small
   enough (a couple of degrees) that segment boundaries are invisible, which
   is exactly why the swing belongs here and not on the slide. */
@keyframes flap-cloth-l {
  0%    { transform: translateX(0) rotate(0deg) skewY(0deg);            animation-timing-function: ease-in-out; }
  12%   { transform: translateX(-.45%) rotate(-.22deg) skewY(-.18deg);  animation-timing-function: ease-in-out; }
  26%   { transform: translateX(.38%) rotate(.18deg) skewY(.15deg);     animation-timing-function: ease-in-out; }
  38%   { transform: translateX(-.2%) rotate(-.1deg) skewY(-.08deg);    animation-timing-function: ease-in-out; }
  44.2% { transform: translateX(0) rotate(0deg) skewY(0deg);            animation-timing-function: cubic-bezier(.48,.02,.16,1); }
  70%   { transform: translateX(0) rotate(-2.4deg) skewY(-1.9deg);      animation-timing-function: ease-out; }
  100%  { transform: translateX(0) rotate(0deg) skewY(0deg); }
}
@keyframes flap-cloth-r {
  0%    { transform: translateX(0) rotate(0deg) skewY(0deg);            animation-timing-function: ease-in-out; }
  12%   { transform: translateX(.45%) rotate(.22deg) skewY(.18deg);     animation-timing-function: ease-in-out; }
  26%   { transform: translateX(-.38%) rotate(-.18deg) skewY(-.15deg);  animation-timing-function: ease-in-out; }
  38%   { transform: translateX(.2%) rotate(.1deg) skewY(.08deg);       animation-timing-function: ease-in-out; }
  44.2% { transform: translateX(0) rotate(0deg) skewY(0deg);            animation-timing-function: cubic-bezier(.48,.02,.16,1); }
  70%   { transform: translateX(0) rotate(2.4deg) skewY(1.9deg);        animation-timing-function: ease-out; }
  100%  { transform: translateX(0) rotate(0deg) skewY(0deg); }
}
@keyframes push-in {
  0%, 48.7% { transform: scale(1.14); filter: brightness(.72) blur(2px); }
  77.7%     { transform: scale(1.03); filter: brightness(.95) blur(0); }
  100%      { transform: scale(1);    filter: brightness(1)   blur(0); }
}
@keyframes sweep {
  0%, 52%  { opacity: 0;  transform: translateX(-78%); }
  62%      { opacity: .9; }
  88%      { opacity: .7; }
  100%     { opacity: 0;  transform: translateX(86%); }
}
@keyframes settle-in {
  0%   { opacity: 0; transform: translateY(22px) scale(.985); }
  70%  { opacity: 1; transform: translateY(-3px) scale(1); }
  100% { opacity: 1; transform: translateY(0)    scale(1); }
}

/* Skipping snaps every layer to its end state immediately. */
.tent-skip .flap-wrap-l, .tent-skip .flap-wrap-r,
.tent-skip .flap-l, .tent-skip .flap-r, .tent-skip .hero-photo,
.tent-skip .hero-shadow, .tent-skip .hero-inner { animation: none !important; }

/* ============================================================
   Page banner. Every page other than the homepage opens the same
   way: one photograph, the same scrim, hemmed by the nav's
   scallop. Shorter than the hero, so the tent entrance stays a
   homepage-only event.
   ============================================================ */
.pagehead { position: relative; overflow: hidden; background: var(--ph-tone, var(--pine)); isolation: isolate; }
.pagehead-photo { position: absolute; inset: 0; z-index: 0; }
.pagehead-photo img { width: 100%; height: 100%; object-fit: cover; object-position: center 45%; }
.pagehead-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(94deg, rgba(15,32,25,.90) 0%, rgba(15,32,25,.72) 46%, rgba(15,32,25,.30) 100%),
    linear-gradient(0deg, rgba(15,32,25,.42) 0%, transparent 52%);
}
.pagehead-inner {
  position: relative; z-index: 2; max-width: 700px;
  padding-block: clamp(54px, 8vw, 96px); color: var(--canvas);
}
.pagehead h1 {
  font-size: clamp(2.3rem, 5.8vw, 4rem);
  font-variation-settings: 'wdth' 88;
  color: var(--canvas);
}
.pagehead-sub { margin: 16px 0 0; font-size: clamp(1.02rem, 1.8vw, 1.18rem); max-width: 48ch; color: #EDE6D8; }

/* ============================================================
   Spec table — dimensions, capacity, power. Product pages live
   or die on these being scannable.
   ============================================================ */
.specs { width: 100%; border-collapse: collapse; }
.specs th, .specs td { text-align: left; padding: 13px 0; vertical-align: top; }
.specs tr { border-top: 2px solid rgba(22,52,42,.13); }
.specs th {
  font-family: var(--body); font-weight: 700; font-size: .78rem;
  letter-spacing: .13em; text-transform: uppercase; color: var(--bark);
  width: 42%; padding-right: 16px;
}
.specs td { font-weight: 600; }

/* ============================================================
   Filter chips
   ============================================================ */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 17px;
  border-radius: 999px; background: transparent; cursor: pointer;
  box-shadow: inset 0 0 0 1.5px rgba(22,52,42,.28);
  font-weight: 600; font-size: .95rem; text-decoration: none;
  transition: background-color .15s, box-shadow .15s;
}
.chip:hover { background: rgba(22,52,42,.06); }
.chip[aria-pressed="true"] { background: var(--ink); color: var(--canvas); box-shadow: none; }

/* ============================================================
   FAQ
   ============================================================ */
[data-faq] details { border-top: 2px solid rgba(22,52,42,.13); }
[data-faq] details:last-of-type { border-bottom: 2px solid rgba(22,52,42,.13); }
[data-faq] summary {
  list-style: none; cursor: pointer; padding: 22px 44px 22px 0; position: relative;
  font-family: var(--display); font-weight: 800; font-size: var(--t-1);
  font-variation-settings: 'wdth' 94; line-height: 1.16;
}
[data-faq] summary::-webkit-details-marker { display: none; }
[data-faq] summary::after {
  content: ''; position: absolute; right: 6px; top: 30px;
  width: 15px; height: 15px;
  border-right: 2.5px solid var(--lawn); border-bottom: 2.5px solid var(--lawn);
  transform: rotate(45deg); transition: transform .22s var(--ease-cloth);
}
[data-faq] details[open] summary::after { transform: rotate(-135deg); top: 34px; }
[data-faq] .answer { padding: 0 8% 26px 0; color: var(--bark); }
[data-faq] .answer p:last-child { margin-bottom: 0; }

/* ============================================================
   Timeline rail — the 1970 story
   ============================================================ */
.years { display: grid; gap: 0; }
.year {
  display: grid; grid-template-columns: 150px 1fr; gap: 28px;
  padding: 28px 0; border-top: 2px solid rgba(22,52,42,.13); align-items: baseline;
}
.year > b {
  font-family: var(--display); font-weight: 800;
  font-size: var(--t-3); color: var(--lawn); line-height: 1;
  font-variation-settings: 'wdth' 88;
}
@media (max-width: 640px) { .year { grid-template-columns: none; gap: 8px; } }

/* Gallery */
.gallery { display: grid; grid-template-columns: 1.6fr 1fr; gap: 12px; }
.gallery figure { margin: 0; overflow: hidden; box-shadow: var(--sh-card); }
.gallery img { width: 100%; height: 100%; object-fit: cover; }
.gallery .g-side { display: grid; gap: 12px; }
@media (max-width: 760px) { .gallery { grid-template-columns: none; } }

/* Two-column prose + aside */
.split { display: grid; grid-template-columns: 1fr 1.12fr; gap: 52px; align-items: start; }
.split-even { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .split, .split-even { grid-template-columns: none; gap: 30px; } }

/* ============================================================
   Availability bar — the ERS Order-by-Date entry point. This is
   the primary conversion path and it appears on every page type.
   ============================================================ */
.datebar {
  background: var(--paper); box-shadow: var(--sh-card);
  padding: 18px 20px; display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px;
}
.datebar-label {
  flex: 0 0 auto; margin: 0; align-self: center;
  font-family: var(--display); font-weight: 800; font-size: 1.26rem;
  font-variation-settings: 'wdth' 92; line-height: 1.1; padding-right: 6px;
}
.datebar-stack { position: sticky; top: calc(var(--nav-h) + var(--scallop)); z-index: 40; }
.field { display: flex; flex-direction: column; gap: 5px; flex: 1 1 150px; min-width: 0; }
.field label {
  font-family: var(--body); font-weight: 700; font-size: .74rem;
  letter-spacing: .15em; text-transform: uppercase; color: var(--bark);
}
.field input, .field select, .field textarea {
  font: inherit; font-size: 1rem; min-height: 50px; padding: 0 13px;
  background: var(--canvas); color: var(--ink);
  border: 1.5px solid rgba(22,52,42,.24); border-radius: 4px;
  width: 100%;
}
.field textarea { min-height: 130px; padding: 12px 13px; line-height: 1.55; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--lawn); }

/* ============================================================
   Trust band
   ============================================================ */
.trust { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: rgba(244,237,223,.20); }
.trust > div { background: var(--pine); padding: 28px 24px; }
.trust > div:first-child { padding-left: 0; }
.trust > div:last-child { padding-right: 0; }
.trust dt {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.55rem, 3.2vw, 2.2rem); line-height: 1; color: var(--marigold);
  font-variation-settings: 'wdth' 88; letter-spacing: -.02em;
}
.trust dd {
  margin: 7px 0 0; font-size: .92rem; letter-spacing: .04em;
  color: #E4DCCB; text-transform: uppercase; font-weight: 600;
}
@media (max-width: 760px) { .trust { grid-template-columns: repeat(2, 1fr); } }

/* ============================================================
   Testimonials
   ============================================================ */
.quote { background: var(--paper); box-shadow: var(--sh-card); padding: 34px 30px 28px; height: 100%; display: flex; flex-direction: column; }
.quote p { font-size: var(--t-1); line-height: 1.42; letter-spacing: -.012em; }
.quote footer { margin-top: auto; padding-top: 16px; font-weight: 700; color: var(--lawn); }
.quote-mark {
  font-family: var(--display); font-size: 3.6rem; font-weight: 800;
  line-height: .82; height: .5em; color: var(--marigold);
  margin: 0 0 14px;
}

/* ============================================================
   Step / checklist rails
   ============================================================ */
.rail { counter-reset: step; display: grid; gap: 2px; }
.rail-item {
  counter-increment: step; display: grid; grid-template-columns: 64px 1fr;
  gap: 20px; align-items: start; padding: 24px 0;
  border-top: 2px solid rgba(22,52,42,.13);
}
.rail-item::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--display); font-weight: 800; font-size: var(--t-2);
  color: var(--marigold); line-height: 1;
}
.band-pine .rail-item { border-top-color: rgba(244,237,223,.20); }

/* ============================================================
   Reveal on scroll — progressive enhancement only. Content is
   VISIBLE by default; the .reveal class is added by JS and a
   scroll fallback runs alongside IntersectionObserver, because
   browser automation and background tabs throttle IO and would
   otherwise leave the page blank.
   ============================================================ */
.js-reveal.reveal-armed { opacity: 0; transform: translateY(20px) scale(.99); }
.js-reveal.reveal-in {
  opacity: 1; transform: none;
  transition: opacity .62s var(--ease-cloth), transform .62s var(--ease-cloth);
}

/* ============================================================
   Footer
   ============================================================ */
.foot { background: var(--ink); color: #DCD5C6; padding-block: 72px 34px; }
.foot h3 {
  font-size: var(--t--1); letter-spacing: .17em; text-transform: uppercase;
  color: var(--sage); font-weight: 700; margin-bottom: 14px;
  font-variation-settings: 'wdth' 100;
}
.foot a { text-decoration: none; }
.foot a:hover { color: var(--marigold); }
.foot-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1.3fr; gap: 40px; }
@media (max-width: 900px) { .foot-grid { grid-template-columns: 1fr 1fr; gap: 32px; } }
@media (max-width: 520px) { .foot-grid { grid-template-columns: 1fr; } }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 1080px) {
  .navlinks { display: none; }
  .navtoggle {
    display: inline-flex; align-items: center; justify-content: center; gap: 9px;
    margin-left: auto; min-height: 46px; padding: 0 16px; border-radius: 999px;
    background: transparent; box-shadow: inset 0 0 0 1.5px var(--ink);
    font-weight: 700; cursor: pointer;
  }
  .callbar { display: flex; }
  body { padding-bottom: 74px; }
  :root { --band: 76px; --gable: 26px; }
  .band-airy { --band: 92px; }
}
@media (max-width: 640px) {
  :root { --band: 64px; --gutter: 18px; --nav-h: 84px; }
  body { font-size: 16px; }
  .brand img { height: 62px; }
  .datebar { padding: 15px 15px 17px; }
  .flap-wrap { width: 74%; }
  .flap-wrap-l { transform: translateX(-90%); }
  .flap-wrap-r { transform: translateX(90%); }
  /* Same one-curve draw, wider parking. */
  @keyframes flap-slide-l {
    0%, 44.2% { transform: translateX(-6%); animation-timing-function: cubic-bezier(.48,.02,.16,1); }
    100%      { transform: translateX(-90%); }
  }
  @keyframes flap-slide-r {
    0%, 44.2% { transform: translateX(6%); animation-timing-function: cubic-bezier(.48,.02,.16,1); }
    100%      { transform: translateX(90%); }
  }
}

/* ============================================================
   Reduced motion — a static open tent, no sequence, no reveals.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js-reveal.reveal-armed { opacity: 1 !important; transform: none !important; }
  .tent-control { display: none !important; }
}

/* ============================================================
   Print
   ============================================================ */
@media print {
  .eavebar, .callbar, .hero-frame, .tent-control, .sheet { display: none !important; }
  body { background: #fff; color: #000; }
}
