/* ============================================================================
   14 · the footer and the sticky bar.  Two root-level objects, both after
   </main>: the oak strip that is the FRONT EDGE of the desk, and the paper
   strip that slides up from below it.

   THE OAK STRIP is the `.oak-strip` material (MATERIALS.md section 11):
   photographed oak from wood.webp, a darkening wash, a lit top chamfer, the
   dark seam where the surface turns into the edge, the shadow it casts back up
   onto the desk, and `color: var(--paper)`. This file adds no face of its own.

   CONTRAST, measured on the REAL GRAIN, not on a token (the script renders the
   footer with its text hidden, samples every background pixel inside each
   text's own box at 1440 and at 390, takes the LIGHTEST one, and ratios
   var(--paper) against it): qa/reports/builder-F/contrast.mjs, which prints
       lightest pixel under any footer text  #724C2A   (@390, the worst case)
       --paper #F7F5F0 against it               6.93:1  the worst shipped pair
       --paper on the strip's median pixel      9.3:1
       wordmark 7.43 · Aviso legal 7.62 · Privacidad 7.31 · Terminos 6.98 @1440
   so every text on oak clears 4.5:1 by at least 2.4 and no local scrim is
   needed.  Rejected on the same measurement, against the brightest pixel
   anywhere on the strip: `--ink` is 3.65:1, which is why the comp's dark ink on
   oak is not what ships, and coral is 1.06:1.
   The pack line is the exception: its price is a claim, so it carries the coral
   EJEMPLO stamp, and coral on oak is 1.26:1.  It rides on a small paper .tag
   (with its pin, like every other .tag on the desk), which is also the only
   surface the stamp material allows.

   GEOMETRY, measured:  the strip is 92px tall at 1440 (24px padding, a 44px
   row), full bleed, content inset by --desk-pad (37px) exactly as the comp has
   it.  Row: wordmark 145px · pack tag 360px · legal nav 230px, on a
   `1fr auto 1fr` grid so the tag is centred.  390: a centred column, 144px.
   With --sticky-h set (the bar on) the strip grows to 160px at 1440 and 208px
   at 390, and the last line of the footer clears the bar's top edge by 27px
   and 24px: measured in qa/reports/builder-F/shots.mjs.

   THE STICKY BAR.  behaviour-contract section 6: fixed, parked at
   translateY(100%), 300ms, transform only, --z-sticky, and `inert` until
   site.js adds .is-on.  1040px wide at 1440 (the comp's 72% of the viewport),
   full bleed below 900px with the button alone.  The footer reserves
   var(--sticky-h) of extra bottom padding, which is the custom property the
   script sets on <html> while the bar is on, so the bar can never cover the
   last line of the footer.
   ========================================================================= */

/* ---------- the oak strip ------------------------------------------------ */
/* The face, the chamfer, the seam, the cast shadow and the paper ink all come
   from `.oak-strip` on the root. Layout and the sticky reserve are all that is
   left here: the local gradients, border-top and box-shadow this file used to
   carry were all replaced by the material and are gone. */
.s-14{
  position:relative;
  padding:var(--sp-5) var(--desk-pad)
          calc(var(--sp-5) + var(--sticky-h,0px) + env(safe-area-inset-bottom,0px));
}

/* `1fr auto 1fr` and not space-between: the legal nav is ~85px wider than the
   wordmark, so space-between would park the pack tag 40px left of the page's
   centre line at every width. Two equal outer tracks put it dead centre. */
.s-14 .s-14-inner{
  display:grid;
  grid-template-columns:1fr auto 1fr;
  align-items:center;
  gap:var(--gap-object);
}

/* the wordmark: the nav's own .wordmark class, so the brand is set once on the
   page (Archivo Black, -.02em) and this file only repaints it for oak. */
.s-14 .s-14-mark{
  justify-self:start;
  margin:0;                        /* .wordmark's own margin-right:auto is for
                                      the nav's flex row, not this grid */
  color:var(--paper);              /* .wordmark sets #111110 on the element, so
                                      it beats the paper ink .oak-strip
                                      inherits: 2.2:1 on the grain if left */
}

/* ---------- the pack line, on paper ------------------------------------- */
/* .tag is not in the materials' transform list (it is normally pinned on
   felt), so its tilt is declared here. */
.s-14 .s-14-pack{
  margin:0;
  white-space:nowrap;
  transform:rotate(var(--rot,0deg));
}
.s-14 .s-14-pack-price{
  color:var(--ink);
  font-weight:700;
}
/* one brass pin, like every other .tag on the desk */
.s-14 .s-14-pack-pin{--px:50%;--py:0%;--pr:16deg}
/* the separators are decoration, not copy, so they live in CSS */
.s-14 .s-14-pack-label::after,
.s-14 .s-14-pack-price::after{
  content:"\00B7";
  margin:0 .55em;
  color:var(--ink-soft);
}

/* ---------- the legal links -------------------------------------------- */
.s-14 .s-14-legal{
  justify-self:end;
  display:flex;
  align-items:center;
  gap:var(--sp-5);
  color:var(--paper);              /* .t-small's own --ink-soft would beat the
                                      paper ink .oak-strip hands down the tree */
}
/* .link ships ink text with a coral underline, and there is no .link-oak the
   way there is a .link-kraft: measured on the real grain, ink is 3.65:1 and
   coral is 1.06:1, so both are repainted in paper here and the hover state
   trades the colour change for a thicker underline. */
.s-14 .s-14-legal .link{
  position:relative;
  color:var(--paper);
  text-decoration-color:var(--paper);
  text-decoration-thickness:1px;   /* paper on oak needs less weight than the
                                      material's 1.5px coral rule on white */
  text-underline-offset:4px;
}
.s-14 .s-14-legal .link:hover,
.s-14 .s-14-legal .link:focus-visible,
.s-14 .s-14-legal .link:active{
  color:var(--paper);
  text-decoration-color:var(--paper);
  text-decoration-thickness:2.5px;
}
.s-14 .s-14-legal .link + .link::before{
  content:"";
  position:absolute;
  left:calc(-1 * var(--sp-3));
  top:.1em;
  bottom:.1em;
  width:1px;
  background:var(--paper);
  opacity:.34;
}

/* ============================================================================
   THE STICKY BAR.  A sibling of the footer, not a child, so it is scoped by
   its own section-prefixed class.  Nothing in the chain above it may carry a
   filter or a transform, or `position: fixed` would resolve against that
   element instead of the viewport: .desk deliberately has neither.
   ========================================================================= */
.s-14-bar{
  --bar-inset:calc(var(--sp-2) + env(safe-area-inset-bottom,0px));

  position:fixed;
  left:0;
  right:0;
  bottom:var(--bar-inset);
  z-index:var(--z-sticky);

  width:min(1040px,calc(100% - 2 * var(--desk-pad)));
  margin:0 auto;

  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--gap-row);
  padding:clamp(8px,.85vw,12px) clamp(12px,1.3vw,20px);
  text-align:left;

  /* parked below the desk edge: 100% of its own height, plus its offset from
     the bottom, plus 16px so --shadow-paper clears the viewport too. */
  transform:translateY(calc(100% + var(--bar-inset) + 16px));
}
.s-14-bar.is-on{transform:translateY(0)}

.s-14-bar .s-14-bar-mark{
  flex:0 0 auto;
  margin:0;
}
.s-14-bar .s-14-bar-cta{
  flex:0 0 auto;
  min-height:48px;                 /* clear of the 44px floor, not level with it */
  display:inline-flex;
  align-items:center;
  justify-content:center;
}

/* One transition on the page's one fixed object: the bar has to announce
   itself without stealing the reader's place, so it rides in from under the
   desk edge rather than appearing on top of the page. Transform only. */
@media (prefers-reduced-motion: no-preference){
  .s-14-bar{transition:transform 300ms cubic-bezier(.2,.8,.25,1)}
}

/* ============================================================================
   MOBILE  < 900px, declared explicitly.
   The footer row becomes a centred column; the bar goes full bleed with the
   button alone, and the safe-area inset moves from its offset into its
   padding so the paper reaches the physical bottom of the screen.
   ========================================================================= */
@media (max-width: 899px){
  /* the strip's own padding is already fluid through --sp-5 / --desk-pad
     (24px / 12px at 390) and keeps the --sticky-h reserve, so it is unchanged. */
  .s-14 .s-14-inner{
    grid-template-columns:1fr;
    justify-items:center;
    gap:var(--gap-row);
  }
  .s-14 .s-14-mark{justify-self:center}
  .s-14 .s-14-pack{
    max-width:100%;
    white-space:normal;
  }
  .s-14 .s-14-legal{
    justify-self:center;
    flex-wrap:wrap;
    justify-content:center;
  }

  .s-14-bar{
    --bar-inset:0px;
    left:0;
    right:0;
    width:auto;
    margin:0;
    border-radius:0;
    padding:10px 12px calc(10px + env(safe-area-inset-bottom,0px));
  }
  .s-14-bar .s-14-bar-mark{display:none}
  .s-14-bar .s-14-bar-cta{
    flex:1 1 auto;
    width:100%;
  }
}

/* Standalone pages (gracias, 404, legal) carry body[data-page]; the sticky buy bar never shows there (manager, 2026-09-22). */
body[data-page] [data-sticky]{display:none}
