/* ============================================================================
   Parama Ceylon — rendering + interaction enhancements
   Loaded after the generated <style> block, so equal-specificity rules here win.
   Selectors are deliberately higher-specificity where they override a rule the
   export writes against `body`, so load order can never silently break them.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   1. Outlined display type
   Every heading is Titan One with `-webkit-text-stroke: Npx`. The stroke is
   centred on the glyph outline AND, by default, painted ON TOP of the fill, so
   half the stroke width erodes the glyph inward on every edge. On a face this
   heavy the joins and counters get chewed up, which is what reads as jagged.
   `paint-order: stroke fill` puts the fill back on top, leaving the interiors
   intact — but it also means only the OUTER half of the stroke stays visible, so
   the headings carry doubled widths in the markup (2px -> 4px, 1.5px -> 3px) to
   land on the same silhouette as before. Verified against the pre-change
   rendering rather than assumed.
   Two headings ("Rooted in Sri Lanka", "Looking for a Product from Sri Lanka")
   shipped with a TRANSPARENT fill, so they rendered as hollow outlines while
   every other heading was solid — visibly a different style. Both were given the
   white fill in the markup, which brings them into this rule; their strokes are
   set to 3px so the visible 1.5px outer edge matches their size-peers.
   Attribute selector rather than `h1, h2` so it follows the stroke wherever the
   export puts it (currently 7 headings across both pages).
------------------------------------------------------------------------------ */
/* The :not() guard is a safety net, not an active exclusion: all seven headings
   now carry a white fill. It matters because paint-order is meaningless without
   one — a transparent-fill heading shows its whole stroke, so applying the rule
   AND the doubled width would render it at twice the intended weight. If a
   future heading is designed hollow, this keeps it out of the treatment. */
[style*="text-stroke"]:not([style*="color: transparent"]) {
  paint-order: stroke fill;
}

/* `optimizeLegibility` forces the full kerning/ligature path and measurably
   changes glyph advances mid-load, which is what makes the hero words shift as
   Titan One swaps in. `auto` is the browser default and already enables kerning
   for display sizes. `html body` outranks the export's own `body` rule. */
html body {
  text-rendering: auto;
}

/* Grayscale AA thins heavy display faces. Let the platform decide for the
   stroked headings specifically, while body copy keeps the export's smoothing. */
[style*="text-stroke"]:not([style*="color: transparent"]) {
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
}

/* ---------------------------------------------------------------------------
   2. Compositing hygiene
   Stale GPU layers are the other half of the "pixelated" report: a layer is
   rasterised once at the scale it had when promoted, then reused. An element
   left on a layer after its reveal finished keeps showing that stale bitmap.
   The reveal engine strips `will-change` per element on completion; this is the
   belt-and-braces pass for anything it misses.
------------------------------------------------------------------------------ */
[data-reveal] {
  will-change: opacity, transform;
}

/* Released elements must NOT keep a will-change hint. */
:not([data-reveal])[data-rv-done] {
  will-change: auto;
}

/* The idle float wrappers animate transform forever. Promoting them once gives
   the compositor a stable layer to translate, instead of the main thread
   repainting the chip (and the text inside it) on every frame. */
[data-float] {
  will-change: transform;
  backface-visibility: hidden;
}

/* ---------------------------------------------------------------------------
   3. Native smooth scrolling
   `scroll-margin-top` clears the sticky nav (min-height 83px desktop / 64px
   mobile) so an anchored section never lands under it — landing under the nav
   was part of why jumping to a section looked broken.
------------------------------------------------------------------------------ */
html {
  scroll-behavior: smooth;
}

#top,
#about,
#products,
#faq,
#contact {
  scroll-margin-top: 104px;
}

@media (max-width: 767px) {
  #top,
  #about,
  #products,
  #faq,
  #contact {
    scroll-margin-top: 24px;
  }
}

/* ---------------------------------------------------------------------------
   4. Card hover states
   Transform + shadow + filter only: all compositor-friendly, no layout work, so
   hovering a grid of nine bento cards cannot cause reflow.
   `--rv-hover-ease` matches the reveal easing so the page has one motion voice.
------------------------------------------------------------------------------ */
:root {
  --rv-hover-ease: cubic-bezier(0.22, 0.7, 0.28, 1);
}

[data-a2-card] {
  /* a transparent base shadow gives the hover shadow something to interpolate
     from — transitioning from `none` snaps instead of easing */
  box-shadow: 0 0 0 rgba(8, 59, 50, 0);
}

[data-a2-card],
[data-a3-card] {
  transition:
    transform 460ms var(--rv-hover-ease),
    box-shadow 460ms var(--rv-hover-ease),
    filter 460ms var(--rv-hover-ease);
}

/* Scoped to devices that actually hover, so a tap on mobile never sticks in a
   hover state. `[data-reveal]` guard: never fight an in-flight reveal. */
@media (hover: hover) and (pointer: fine) {
  [data-a2-card]:not([data-reveal]):hover,
  [data-a3-card]:not([data-reveal]):hover {
    transform: translateY(-8px);
  }

  /* Only the About photo cards take a shadow on hover. The bento cards are now
     light-on-light with a 1px border, and a drop shadow under them read as
     heavy and muddied that border, so they lift without one. */
  [data-a2-card]:not([data-reveal]):hover {
    box-shadow: 0 18px 40px -12px rgba(8, 59, 50, 0.32);
  }

  /* Photographic cards lift their midtones slightly; flat/gradient cards would
     just look washed out, so brightness is limited to the image cards. */
  [data-a2-card]:not([data-reveal]):hover {
    filter: brightness(1.06) saturate(1.04);
  }

  /* FAQ rows are the one list that reads as clickable, so they get a tint and a
     small inward nudge rather than a lift. */
  [data-faq-row] {
    transition:
      background-color 320ms var(--rv-hover-ease),
      padding-left 320ms var(--rv-hover-ease);
  }

  [data-faq-row]:not([data-reveal]):hover {
    background-color: rgba(0, 111, 19, 0.035);
    padding-left: 8px;
  }
}

/* ---------------------------------------------------------------------------
   5. Reduced motion
   The export's own reduced-motion block only clamps animation/transition
   duration; it leaves smooth scrolling and the hover transforms in place.
------------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  [data-a2-card],
  [data-a3-card],
  [data-faq-row],
  [data-float] {
    transition: none !important;
    will-change: auto;
  }

  [data-a2-card]:hover,
  [data-a3-card]:hover {
    transform: none;
    filter: none;
  }
}

/* ---------------------------------------------------------------------------
   6. Mobile typography corrections
   Two opposite problems, both from the export hard-coding px sizes that were
   chosen at desktop width and never revisited for a 375px screen.
------------------------------------------------------------------------------ */
@media (max-width: 767px) {
  /* TOO LARGE — the sourcing cards' titles were 28px while the SECTION heading
     above them ("Looking for something else?") is 27px, so a card title
     outweighed the heading it sits under: the hierarchy read upside down. They
     were also inconsistent with each other (three at 28px, one at 24px).
     21px puts them clearly below the section heading and levels them out.
     !important is required, not stylistic: the sizes are inline attributes. */
  [data-sc-copy] > p:first-of-type {
    font-size: 21px !important;
    line-height: 28px !important;
  }

  /* TOO SMALL — the two glass pills on the honey card are authored at 10px.
     Even with the stage zoom now near 1:1 that is below a comfortable reading
     size on a phone, so correct for whatever zoom is actually applied:
     --stage-zoom is published by _scaleStage, and dividing by it means the
     declared size lands at the intended RENDERED size whatever the viewport.
     Matched by the inline declaration so it tracks the label wherever it moves. */
  [data-a3-card] [style*="font-size: 10px"] {
    font-size: calc(13px / var(--stage-zoom, 1)) !important;
    line-height: 1.32 !important;
  }

  /* the pills carry a fixed inline height sized for 10px text; let them grow to
     fit the larger type rather than clipping it */
  [data-a3-card] div:has(> [style*="font-size: 10px"]) {
    height: auto !important;
    min-height: calc(59.4px / var(--stage-zoom, 1));
  }
}

/* ---------------------------------------------------------------------------
   7. Sourcing cards: stop clipping their own copy on mobile
   The text panel is `flex: 520 1 0` inside a column flex parent that clips
   (`overflow: hidden`). A zero flex-basis means the panel takes a SHARE of the
   available height rather than the height its text needs, so at 375px it
   settled at 188px and cut the body copy off mid-sentence — and hid the "Read
   more" link entirely, 64-92px below the fold of its own panel. Sizing to
   content is the fix; the cards are stacked vertically at this width, so there
   is nothing for a taller panel to disturb.
------------------------------------------------------------------------------ */
@media (max-width: 767px) {
  [data-sc-content] {
    overflow: visible !important;
  }

  /* `1 0 auto`, not `0 0 auto`: basis auto means it starts at its content height
     so nothing can be cut, grow 1 lets it fill the card, and shrink 0 stops it
     being squeezed back below that content. The original `520 1 0` had a ZERO
     basis, which is what made it take a share of the height instead of what its
     text needed. */
  [data-sc-content] > div:has(> [data-sc-copy]) {
    flex: 1 0 auto !important;
    overflow: visible !important;
  }

  /* The four cards stack in a column here, so each sized to its own content and
     they ended up 310/282/306/282 tall — the titles wrap to two or three lines
     and the body copy to four or five. A grid with equal auto-rows levels them
     against the tallest without hardcoding a height, so it keeps working if the
     copy changes. */
  [data-sc-card] {
    min-width: 0;
  }

  div:has(> [data-sc-card]) {
    display: grid !important;
    grid-auto-rows: 1fr;
  }

  /* With the cards levelled, the slack inside each one has to go somewhere. The
     photo is `flex: 440 1 0` — an enormous grow factor against a zero basis — so
     it swallowed all of it and grew from its intended 200px to 227px, leaving
     the panels still 27px apart. Pinning the photo to --scPhotoH hands the slack
     to the panel instead, which is the box whose height should match. */
  [data-sc-photo] {
    flex: 0 0 auto !important;
  }
}

/* ---------------------------------------------------------------------------
   8. Pinned sourcing section must be opaque
   While pinned the section is `position: fixed` and covers the viewport, but it
   was authored with no background of its own. Everything still scrolling behind
   it — the product grid above, the story section below — showed straight
   through, which reads as two sections overlaid on each other. The page
   background is white, so this is invisible when the section is NOT pinned.
------------------------------------------------------------------------------ */
[data-screen-label^="04"] {
  background: #ffffff;
}

/* The story section pins too (see _storyConverge), so it needs the same opaque
   background for the same reason as section 04 — otherwise the FAQ below and
   the sourcing section above show through it while it is position: fixed. */
[data-screen-label^="05"] {
  background: #ffffff;
}

/* ---------------------------------------------------------------------------
   9. About cards: shorter on mobile
   --cardH is 552px at every width, and it drives only the three [data-a2-card]
   photo cards. At 375px the cards are ~280px wide once the stage zoom applies,
   so 552px made each one a 1:1.8 portrait slab — three of them meant well over
   a viewport of scrolling each. 380px lands them near a 4:5 crop.
   `html:root` rather than `:root` so this outranks the export's own token block
   regardless of stylesheet order.
------------------------------------------------------------------------------ */
@media (max-width: 767px) {
  html:root {
    --cardH: 380px;
  }

  /* The caption gradient is a fixed 282px anchored to the card's bottom edge —
     51% of a 552px card, but 74% of a 380px one, which would wash most of the
     photograph out. Scaled to keep the original proportion. */
  [data-a2-card] > div:first-child {
    height: 195px !important;
  }
}

/* ---------------------------------------------------------------------------
   10. Mobile nav menu must sit above the hero
   The nav bar carries `z-index: 30`, but at =<767px the export sets
   --navSticky: static and z-index has NO EFFECT on a static element. Its intro
   animation (pNavIn) leaves a transform behind, which does create a stacking
   context — one with no z-index of its own — so the whole nav, dropdown
   included, painted below the hero's `position: relative; z-index: 1` children.
   The open menu ended up underneath the headline.
   Switching the token to `relative` keeps the nav exactly where it is in flow
   (it has `top: 0`, so there is no offset, and it still does not stick) while
   letting its existing z-index: 30 actually apply. Changing the token avoids
   needing !important to beat the inline `position: var(--navSticky)`.
------------------------------------------------------------------------------ */
@media (max-width: 767px) {
  html:root {
    --navSticky: relative;
  }
}

/* ---------------------------------------------------------------------------
   11. Spices card interior: make it fluid on mobile
   Every child of this card is absolutely positioned in pixels chosen for the
   authored 488px card. The card is 364px on a phone, so all four overflowed to
   the right and were clipped by the card's overflow: hidden — the progress bars
   by 82px, the title by 63px, the arc backdrop by 40px, and the girl by 17px,
   which also pushed her off-centre.
   Each px value is re-expressed as its share of that 488px design width, so the
   interior now scales with the card and keeps the proportions the design
   intended. That both centres the figure (the design already had her centred:
   105/488 = 21.5%, and dead centre for her width is 21.6%) and makes her
   smaller, 207px instead of 277px at this card width.
   !important throughout is not stylistic — these are inline attributes.
------------------------------------------------------------------------------ */
@media (max-width: 767px) {
  /* arc backdrop behind the figure: 81px / 326px of 488 */
  [data-a3-card] > div[style*="border-radius: 160px 160px 0px 0px"] {
    left: 16.6% !important;
    width: 66.8% !important;
  }

  /* card title: 35px of 488, spanning to a matching gutter on the right */
  [data-a3-card] > p[style*="width: 397px"] {
    left: 7.17% !important;
    right: 7.17% !important;
    width: auto !important;
  }

  /* the figure: 105px / 277px of 488 */
  [data-a3-card] > [data-a3-img][style*="width: 277px"] {
    left: 21.52% !important;
    width: 56.76% !important;
  }

  /* progress bars: three fixed 131/132px bars plus two 12px gaps came to 418px
     against 294px of usable width. Let them share the row instead. */
  [data-a3-card] > div[style*="top: 41px"][style*="gap: 12px"] {
    left: 7.17% !important;
    right: 7.17% !important;
  }

  [data-a3-card] > div[style*="top: 41px"][style*="gap: 12px"] > div {
    flex: 1 1 0 !important;
    width: auto !important;
  }
}

/* ---------------------------------------------------------------------------
   12. Pinned accordion: stop the row height changing between steps
   The card row is a flex row with align-items: stretch, so every card takes the
   height of the tallest. A COLLAPSED card is animated to width 0, and at zero
   width its panel's text wraps one character per line — an enormously tall
   intrinsic height that leaked out and drove the whole row. Because a different
   set of cards is collapsed at each step, the row resized as the accordion
   advanced: 610px on steps 1, 2 and 4 but 562px on step 3, a visible 48px jump
   mid-scrub.
   The rail and the photo are both already `height: var(--scH)`; the text panel
   was the one box allowed to exceed it. Giving the content box that same
   definite height makes the intrinsic height of the collapsed panels irrelevant
   and holds every step at --scH. The active panel's content is ~254px inside a
   380-520px box, so nothing is at risk of clipping.
------------------------------------------------------------------------------ */
@media (min-width: 1024px) {
  [data-sc-content] {
    height: var(--scH);
  }
}

/* The hero pins during its exit (see _heroConverge), so like sections 04 and 05
   it needs a background of its own — otherwise the About section scrolling
   behind shows through while the hero is position: fixed. */
#top {
  background: #ffffff;
}

/* ---------------------------------------------------------------------------
   13. Primary buttons: soft sheen, and no green fill
   Replaces an earlier hard-edged streak that swept in ~1.2s and read as a line
   being drawn across the pill. This is the opposite treatment: a wide, blurred,
   low-contrast band that drifts across over three seconds, with a long rest
   between passes, plus a fixed highlight along the top edge so the pill reads as
   a lit surface even while nothing is moving.

   The buttons are selected by their fill span rather than by class or text, so
   "all primary buttons" keeps holding as copy changes. There are four: the hero
   CTA, both sourcing CTAs and the contact card's.
------------------------------------------------------------------------------ */

/* The export ships two separate green treatments on these buttons, and both are
   unwanted:
   1. [data-cta-fill] is a rgb(0,111,19) panel that initCtaSweep wipes across
      each CTA once. Hidden rather than deleted so :has() still finds it and the
      component's own animation keeps running harmlessly against it.
   2. ctaEnter writes background: rgb(15,87,70) inline on hover, which turned the
      near-black pill bright green. Overridden to a gentle lift of its own base
      colour, so hovering brightens the button instead of recolouring it.
      !important is required: the handler writes an inline style. */
a:has(> [data-cta-fill]) > [data-cta-fill] {
  display: none !important;
}

@media (hover: hover) and (pointer: fine) {
  a:has(> [data-cta-fill]):hover {
    background: rgb(28, 62, 10) !important;
  }

  /* the contact card's button is white; leave its background alone and let the
     lift and shadow ctaLightEnter already applies carry the hover */
  #contact a:has(> [data-cta-fill]):hover {
    background: rgb(255, 255, 255) !important;
  }
}

/* fixed top-edge highlight — the "lit surface" read, with no motion at all */
a:has(> [data-cta-fill])::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.15) 0%,
    rgba(255, 255, 255, 0.04) 45%,
    rgba(255, 255, 255, 0) 70%
  );
}

/* the drifting sheen: wide, blurred and dim, so it is light moving over the
   surface rather than an edge travelling across it */
a:has(> [data-cta-fill])::after {
  content: "";
  position: absolute;
  top: -45%;
  bottom: -45%;
  left: 0;
  width: 78%;
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.07) 30%,
    rgba(255, 255, 255, 0.18) 50%,
    rgba(255, 255, 255, 0.07) 70%,
    rgba(255, 255, 255, 0) 100%
  );
  /* the blur is what removes the "drawn line" quality */
  filter: blur(7px);
  transform: translateX(-130%);
  animation: paramaSheen 8s cubic-bezier(0.4, 0, 0.35, 1) infinite;
}

@keyframes paramaSheen {
  0%,
  26% {
    transform: translateX(-130%);
  }
  64%,
  100% {
    transform: translateX(165%);
  }
}

/* On the white contact button a white sheen is invisible, and a white top
   highlight does nothing either, so both are inverted to a soft dark tint. */
#contact a:has(> [data-cta-fill])::before {
  background: linear-gradient(
    180deg,
    rgba(10, 82, 60, 0) 55%,
    rgba(10, 82, 60, 0.05) 100%
  );
}

#contact a:has(> [data-cta-fill])::after {
  background: linear-gradient(
    100deg,
    rgba(10, 82, 60, 0) 0%,
    rgba(10, 82, 60, 0.06) 30%,
    rgba(10, 82, 60, 0.14) 50%,
    rgba(10, 82, 60, 0.06) 70%,
    rgba(10, 82, 60, 0) 100%
  );
}

@media (prefers-reduced-motion: reduce) {
  a:has(> [data-cta-fill])::after {
    animation: none;
    opacity: 0;
  }
}

/* ---------------------------------------------------------------------------
   14. Bento: drop the stacked pair on mobile
   Hides "Flexible Product Sourcing / From established exports" and the Parama
   Ceylon logo card. Those two are the only children of one bento unit -- a
   column that stacks them -- so hiding the unit removes both cards and the 24px
   gap between them in one go, rather than leaving an empty wrapper behind.

   Matched structurally rather than by colour or copy: a bento unit (grandchild
   of the stage) holding exactly two stacked cards. Selecting on the inline
   background would not survive, because the component rewrites those style
   attributes and re-serialises `rgb(231,241,178)` with spaces.
------------------------------------------------------------------------------ */
@media (max-width: 767px) {
  /* !important is required, not stylistic: the wrapper carries an authored
     inline `display: flex`, which outranks a stylesheet rule of any
     specificity. */
  [data-stack-width] > div > div:has(> [data-a3-card] + [data-a3-card]):not(:has(> :nth-child(3))) {
    display: none !important;
  }
}
