/* ================================================= dovanų kuponai =======
   Gift packages: the third kind of thing on /pasiulymai/, and the one the
   client could not find.

   The page already carried two. A LIVE DEAL (.of-live-section) is a discount
   that stops — navy band, cold ink, a countdown on every card. A STANDING
   OFFER (.of-standing-section) is an arrangement that is always true — cream
   band, no clock, no end date. Gifts were rendered as neither, and the
   client's note after the first pass was exactly: „I still dont see separation
   between gifts and offers?"

   The separation is deliberately NOT a different card shape. The client asked
   for one card — square, fully covered by the image, gradient at the bottom
   carrying the title, the big figure in the corner — and giving gifts a
   different silhouette would have thrown that away to solve a problem that is
   not about silhouette. What differs is everything that goes into the shape,
   and all of it is legible before a word is read:

     TEMPERATURE  the veil over a deal is navy (#081c2b, the site's dark); the
                  veil over a gift is warm brown (accent-2, #4f3b28). Two rows
                  of otherwise identical cards read as two different objects at
                  arm's length, and still do out of focus or in a screenshot.
     THE FIGURE   a price, not a percentage. „129 €" and „−20 %" occupy the same
                  corner and mean opposite kinds of thing.
     THE CORNER   a „Dovanų kuponas" tag with a knot on it, in the slot where a
                  live deal puts its ticking clock. The one place on the card
                  where the eye is trained to find urgency now holds the word
                  „dovana".
     THE ROW      „Galioja 12 mėn." — a span that begins when you pay, not a
                  deadline that runs down whether you pay or not.

   Everything here is prefixed `gf-` so it can never collide with the `of-`
   rules next door, which are being edited independently.

   WHAT THIS SHEET DELIBERATELY DOES NOT STYLE. The band itself — the ground
   colour, the padding and the seam of .of-gifts-section, and the .of-head
   block inside it — belongs to pp-offers.css, which sets all three sections'
   grounds together as one decision (navy / light / cream). An earlier draft of
   this file painted the band sand from here. It even worked, because this
   sheet is linked after that one and the selectors tie on specificity — which
   is exactly why it was taken out: a rule that silently wins a tie is a rule
   nobody knows they are fighting, and the next person to change the ground
   next door would change it and see nothing happen. Three grounds set in three
   places is not a palette, it is three accidents. If the light ground turns
   out not to separate the gift band from the cream one below it, that is one
   line to change in pp-offers.css, next to the other two.

   The popup is the offers' popup (.dl-modal) with two rows of its own at the
   foot of this file. One dialog language for all three kinds of offer. */

/* The one band-level rule kept here, and it is keyed to the host ATTRIBUTE
   rather than the class so it cannot tie with anything in pp-offers.css. It is
   not decoration: widgets/gifts.js promises the section stays invisible when
   there is nothing giftable or the fetch fails, and several of the template's
   own rules set `display` on .section, which beats the UA's
   [hidden] { display: none } and would leave an empty band with a heading over
   nothing. This is that promise, written down. */
[data-gifts-live][hidden] { display: none; }

/* ------------------------------------------------------- the grid ------
   Declared against the host attribute rather than inherited from .of-grid.
   The markup carries both, so this is not a fallback — it is independence:
   pp-offers.css is owned by the live-deals work and its grid is free to change
   shape for reasons that have nothing to do with gifts. An attribute selector
   and a class have the same specificity, and this sheet loads after that one,
   so whichever way .of-grid moves the gift grid keeps these columns.

   2026-08-29, savininkas, twice in one day. First „i think maybe the cards
   shouldnt be square, maybe make them 2x2 and a bit less tall, they will look
   more cupon-y" — so the square went. Then, on a ~1990px screen, „a card takes
   almost full page on my screen its not good", which is what a fixed
   `repeat(2, 1fr)` does: it has no opinion about how big a card should BE, only
   about how many there are, so on a 1800px container each one came out 880px
   wide and one gift filled the viewport.

   `auto-fit` with `minmax(300px, 560px)` states the thing that is actually
   true — a coupon is between 300 and 560 pixels wide, and the number of them
   per row is whatever fits. Measured, that is 560×350 at 1990, at 1440 and at
   1200 alike, roughly a third of the viewport's height instead of all of it,
   and one column on a phone with no breakpoint asked to do it. `auto-fit`
   (not `auto-fill`) collapses the empty tracks so a single coupon is not
   left-aligned against three ghosts, and `justify-content: center` puts the
   short last row under the middle of the ones above it.

   The odd-card-out full-width span that used to be here is gone with the fixed
   columns: at 12:5 across a wide container it was the single biggest slab on
   the page, which is the thing the client was complaining about.

   Every number is copied from .of-grid in pp-offers.css DELIBERATELY rather
   than shared with it. The independence argument above is unchanged — the
   markup carries both classes, this sheet loads second, so a change to .of-grid
   cannot silently reshape the gift band without someone noticing the two lists
   have drifted. */
[data-gifts-list] {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 560px));
  justify-content: center;
  gap: 22px;
}

/* The tear-off stub's palette, and the only three declarations that make the
   shared .of-stub / .of-perf rules in pp-offers.css a GIFT stub.

   NOTHING READS THESE TODAY. 2026-08-29, savininkas: „for gift cupons we dont
   need stubs", so widgets/gifts.js stopped calling its stubHtml() and a coupon
   renders no .of-stub and no .of-perf. They stay because the function they
   dress is still there and three custom properties cost nothing, and because
   the argument below is the expensive part — it took two contrast measurements
   to settle and would have to be made again from scratch. Anything that turns
   the stub back on gets it for free; nothing else on the card is affected.

   Brown face, cream ink. The live deals put a cream stub on their navy band and
   the standing offers a navy one on cream; the third band is the page's own
   near-white paper, so the gift stub takes accent-2 — which is also the veil's
   colour, so the tear-off and the scrim over the photograph are one material.
   White on #4f3b28 measures 10.6:1, and the alternative that was tried first —
   brass, to rhyme with the ribbon — measures 3.7:1 and cannot carry a 12px
   label.

   --of-ground is not decoration either: the punched holes at each end of the
   perforation are full circles positioned half outside the frame, and they are
   painted in the SECTION's ground so that the half inside the card reads as a
   bite taken out of it. Give it the wrong colour and the notch becomes a dot.
   The gift band's ground is bg-1, set in pp-offers.css; this is the one place
   that fact has to be repeated, and it is repeated as a variable rather than as
   a second `background-color` for exactly that reason. */
[data-gifts-live] {
  --of-chip-face: var(--colors-color-accent-2);
  --of-chip-ink: var(--colors-color-light);
  --of-ground: var(--colors-color-bg-1);
}

/* ------------------------------------------------------- the card ------
   A button that has been talked out of looking like one. Every one of these
   resets exists because a UA stylesheet puts something on <button> that has no
   business on a 400px photograph: a border, a grey face, a centred 13px system
   font, and on Safari an -webkit-appearance that ignores most of the above. */
.gf-card {
  display: block;
  position: relative;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.gf-frame {
  position: relative;
  display: block;
  overflow: hidden;
  /* Was 1/1, then 3/2. „A bit less tall" — a coupon is a landscape object, a
     ticket rather than a tile, and the shape is doing that work before any of
     the wrapping does. 8:5 is the offers' ratio; the two bands are meant to be
     the same object. `overflow: hidden` also matters more than it did: it is
     what clips the punched holes to semicircles, and what guarantees the
     ribbon — which runs the full height and width — can never contribute a
     pixel to the page's scroll width. */
  aspect-ratio: 8 / 5;
  /* THE CARD'S STACK, STATED ONCE, and the only place any of these numbers
     mean anything. `isolation: isolate` is what makes that true: without it
     .gf-frame is position:relative with z-index auto, so it is NOT a stacking
     context and every z-index below is resolved against some ancestor far up
     the page, shared with every other coupon in the grid. With it the whole
     stack is local to one card and can be read here:

       auto   .gf-img      the photograph
       1      .gf-veil     the warm scrim, over the room only
       2      .gf-top      the „Dovanų kuponas" tag
       2      .gf-bottom   title, inclusion chips, validity, „Plačiau"
       4      .gf-ribbon   the two bands AND the bow — over all of the above

     Nothing else inside a coupon sets a z-index; the offers' .of-stub (3) and
     .of-perf (4) never appear on this card, which has no tear-off. */
  isolation: isolate;
  /* AND THE BACKDROP ROOT IS HERE, which is a different thing from the stacking
     context above and does not come for free with it: `isolation: isolate` was
     measured on /kambariai/ and changed Chrome's layer tree by exactly nothing.

     Every `.gf-tile` in the rail carries a `backdrop-filter`, and a
     backdrop-filter samples everything painted from here down to it. Without a
     root at the card, „here" is the document — 1440x4156 on this page — and
     each of the 44 tiles would hold a surface that size to blur a 242x70 strip
     of photograph. That is the /kambariai/ fault exactly: 22 filtered elements
     against a 5210px root cost 1061 MB of compositor surface. `will-change:
     filter` is the one declaration that measurably moved the root there;
     `isolation` and `contain: paint` did not. See memory backdrop-filter-white-bar. */
  will-change: filter;
  border-radius: var(--spacing-radius-main, 16px);
  /* Warm, so the moment before the photograph decodes is a card and not a
     hole punched in the band. */
  background-color: var(--colors-color-bg-3);
}

.gf-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s cubic-bezier(.16, 1, .3, 1);
}
.gf-card:hover .gf-img { transform: scale(1.04); }

/* ---- the giftwrap ------------------------------------------------------
   The client asked for it back („didnt we have some gift wrap graphic made for
   the gift cupons?"); widgets/gifts.js carries the bow itself and the argument
   for which of the five drawn variants it is. What lives here is the palette,
   the geometry, and the two decisions that keep it from breaking the card.

   FLAT, TWO-TONE, NO GRADIENT. Settled on 28 Aug in bow2.html, whose heading is
   literally „Kaspinas — plokščias, be gradiento". Brass band, sand bow, and
   nothing pretending to be satin. The one non-flat thing on the band is a
   1px inset light edge on its left/top and a dark one on its right/bottom,
   which is the b2 swatch from that same sheet: it is a fold, not a sheen, and
   without it the vertical band and the horizontal band merge into one brass
   cross at the crossing instead of reading as one ribbon lying over another.

   THE STACK: the ribbon is on top of everything. 2026-08-29, savininkas, of
   the ribbon: „They should be on top of everything - text shadows chips…" The
   bands used to paint under .gf-veil so the scrim dimmed the brass by exactly
   as much as it dimmed the room, and the type sat in front of both. That is
   the arrangement he was looking at and asked to change: a ribbon that passes
   BEHIND the title is not lying on the coupon, it is printed on it. So
   .gf-ribbon is at 4 — see the stack listed on .gf-frame — above the veil,
   above the tag, above the title, above the chip strip and above „Plačiau",
   and the bow comes with it because it is a child.

   WHAT THAT COSTS, and how it is paid. Undimmed brass is #a07f57, which is
   3.7:1 against white — under the AA floor for the 12px caps and marginal for
   the title — and the vertical band at 72 % crosses all three rows of the
   bottom block. The band is opaque, so the glyphs it covers are simply not
   there to be read; what has to survive is the type at its two edges, where
   white ink meets light satin. That is paid on the TYPE, with the navy
   text-shadow the source contact sheet used for exactly this case (see
   „Deviations" in <scratchpad>/coupons/bows/notes.md — „Added a navy
   text-shadow under 760 px so white type stays legible over light satin"),
   and NOT by dimming the ribbon, which is the thing he just asked to stop.
   The shadow is set once, in „the type the bands cross" below the veil.

   pointer-events: none because the whole card is one button and the ribbon has
   no business being a hit target inside it; it would also sit between the
   pointer and the chip strip, which is a scrolling region. */
/* THE RIBBON'S GEOMETRY LIVES HERE, on the frame, not on .gf-ribbon.
   Custom properties inherit down; they do not reach siblings. .gf-bottom
   needs --gf-cross-x and --gf-band to work out where to stop short of the
   band on a phone, and while these sat on .gf-ribbon that var() resolved to
   nothing, the calc() was invalid, and the browser dropped the whole
   declaration in silence — which is why the title still ran under the band
   after the rule that was supposed to prevent it had been written. */
.gf-frame {
  --gf-band: 22px;    /* the ribbon's width, both ways, so the crossing is square */
  /* Right of centre, where a wrapped parcel's ribbon sits and where it takes
     the least of the title. The number stays put because the BOW is registered
     to it: the knot lands on the crossing only because both bows are padded
     onto a shared 1.34 canvas with the knot at (50 %, 42 %). Moving it means
     re-registering the assets. */
  --gf-cross-x: 72%;
  /* Measured against the 8:5 frame, not guessed: the tag ends around 46px down
     a 350px card and the title block starts around 204px, so the empty strip is
     46–204 and the knot sits at 126. The tails hang BELOW the knot, which is
     why this is above the middle rather than on it. */
  --gf-cross-y: 17%;
  --gf-bow-w: clamp(130px, 34%, 200px);
  --gf-brass: #a07f57;
  --gf-knot: #8a6c48;
  --gf-sand: #d2c5ac;
}


.gf-ribbon {
  /* Over the veil, the tag, the title and the chips — 2026-08-29, savininkas:
     „They should be on top of everything - text shadows chips...". The type
     under it keeps a navy text-shadow; see .gf-title. */
  z-index: 4;
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The bands are the SAME satin as the bow — the second half of the Magnific
   set, straightened and rotated (see the BOW note in widgets/gifts.js). A CSS
   gradient under a photographed bow reads as two different objects; one
   photograph of one ribbon under one light reads as one.

   `background-size: 100% 100%` stretches rather than repeats, deliberately.
   Tiling a 1000px length into a 350px card would put a seam wherever the loop
   closed, and the sheen — which is the whole reason to use a photograph — runs
   the full length of the render. Stretching scales the highlight with the card
   and never seams. The drop-shadow is what sets the band on the photograph
   rather than in it, and it matches the bow's own contact shadow. */
.gf-ribbon::before,
.gf-ribbon::after {
  content: "";
  position: absolute;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  filter: drop-shadow(0 2px 5px rgb(0 0 0 / 42%));
}
.gf-ribbon::before {
  top: 0;
  bottom: 0;
  left: var(--gf-cross-x);
  width: var(--gf-band);
  transform: translateX(-50%);
  background-image: url("/images/pp/gift-band-v.webp");
}
.gf-ribbon::after {
  left: 0;
  right: 0;
  top: var(--gf-cross-y);
  height: var(--gf-band);
  transform: translateY(-50%);
  background-image: url("/images/pp/gift-band-h.webp");
}
.gf-ribbon::before {
  --gf-dir: 90deg;
  top: 0;
  bottom: 0;
  left: var(--gf-cross-x);
  width: var(--gf-band);
  transform: translateX(-50%);
}
.gf-ribbon::after {
  --gf-dir: 180deg;
  left: 0;
  right: 0;
  top: var(--gf-cross-y);
  height: var(--gf-band);
  transform: translateY(-50%);
}

/* The knot, not the drawing, is what has to land on the crossing. In the bow's
   170×130 viewBox the knot is the rect at y 48–67, whose centre is 44 % of the
   height — hence -44 % rather than the -50 % the contact sheet used, which
   floated the whole bow a few pixels high and left the tails hanging off-band.
   The tails then fall BELOW the crossing, which is the other reason
   --gf-cross-y is above centre rather than on it. */
/* The bow no longer needs a z-index of its own to clear the veil — .gf-ribbon
   is above everything now and, carrying a z-index, is a stacking context, so
   this number is LOCAL to the ribbon and the only thing it has to beat is the
   two bands. 1 is that, and stating it is still worth a declaration: the bands
   are pseudo-elements of the same parent, and a bow that painted under the
   crossing would show a brass seam across the knot. */
.gf-bow {
  position: absolute;
  z-index: 1;
  left: var(--gf-cross-x);
  top: var(--gf-cross-y);
  width: var(--gf-bow-w);
  /* -42%, not -50% and not the -44% the SVG needed: the knot sits at 42% of
     the shared 1.34 canvas both bows are padded onto. That padding is the
     registration — see the BOW note in widgets/gifts.js. */
  transform: translate(-50%, -42%);
}
.gf-bow-img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 6px 14px rgb(0 0 0 / 50%));
}

/* Two gradients in one layer, in accent-2 brown rather than the deals' navy.
   This single substitution is doing most of the work of separating the two
   sections, so it is worth being explicit about why it is safe: neither
   gradient reaches the middle of the frame, so the photograph is still a
   photograph and the warmth reads as a scrim rather than as a filter over the
   room. The top one carries the price, the bottom one the title — a bright
   room photographs white in exactly the two places the type goes. */
.gf-veil {
  position: absolute;
  z-index: 1;   /* over the photograph, under the type and under the ribbon */
  inset: 0;
  pointer-events: none;
  /* MUCH lighter than the first rebuild, which stacked a 66% top scrim on an
     88% bottom one in warm brown and turned every coupon into a mud-coloured
     rectangle with a room somewhere inside it. The version the client approved
     on 28 Aug (bowA.png) is a clean photograph with the type sitting in a
     gradient at the bottom and nothing over the middle at all. The top scrim
     is now only as much as the „Dovanų kuponas" tag needs, and the bottom one
     stops well short of the ribbon's crossing. */
  background-image:
    linear-gradient(180deg, rgb(46 33 20 / 34%) 0%, rgb(46 33 20 / 0%) 20%),
    linear-gradient(0deg, rgb(46 33 20 / 84%) 0%, rgb(46 33 20 / 34%) 26%, rgb(46 33 20 / 0%) 52%);
}

/* ---- the card's three type styles, and only three ----------------------
   2026-08-29, savininkas: „why is this a font mish mash?", and then, of these
   coupons beside the offers above them: „why are the fonts inconsistent with
   the limited time offers?" The first note got the coupon down to three styles
   of its own. The second is the one that matters more, because three of the
   wrong three is still two sections that do not look related — the coupon was
   set in Instrument Sans where every other card title on the site is Instrument
   Serif, and the reader can see that from across the room.

   So the three are no longer this card's three. They are the SAME THREE the
   offer card next door uses, and the argument for each of them is written once,
   beside the offer card, in public/css/pp-offers.css — „the card's three type
   styles, and only three". Repeating the numbers here is what let the two
   sections drift apart in the first place, so this sheet names the same tokens
   and says which element takes which:

     THE CAPS   .label's tokens — the „Dovanų kuponas" tag, the inclusion
                chips, „Plačiau". The offer card spends it on the unit under
                the figure and its own „Plačiau".
     THE TITLE  .text-h4 — Instrument Serif. The name of the present. Set on
                the element in widgets/gifts.js, which carries `text-h4`
                exactly as the offer card's title does; there is deliberately
                no .gf-title font rule here to drift from it.
     THE BODY   the card's inherited 16px Instrument Sans (14 on a phone). The
                validity and the struck compare-at — the same two jobs the
                offer card's meta line gives it, in the same row, under the
                same title.

   The VALIDITY and the STRUCK PRICE moved out of the small print to get there,
   and that is the one visible change of mind. They were caps because they were
   „annotations"; on the offer card the equivalent line — „iki 2027 m. kovo 31
   d." and its own struck figure — has always been body type, distinguished
   from the title by colour and from each other by the strike alone. Making the
   coupon match is what the client asked for, and it costs nothing: both stay
   quiet through opacity (.82 and .68, the offer card's own numbers) rather
   than through a size of their own.

   The CHIPS keep caps rather than taking a fourth, quieter, sentence-case
   size: a fourth style introduced to make long Lithuanian labels a little
   easier to read would be re-committing the exact fault. The labels stay short
   instead — that is what the chip is for, and the full sentence with its
   subtitle is in the popup. */
.gf-tag,
.gf-more,
.gf-chip-text {
  font-family: var(--text-label-font-family);
  font-size: var(--text-label-font-size, 12px);
  line-height: var(--text-label-line-height);
  font-weight: var(--text-label-font-weight);
  letter-spacing: var(--text-label-letter-spacing);
  text-transform: uppercase;
}

/* ---- the type the bands cross -----------------------------------------
   The whole cost of putting the ribbon on top, paid in one declaration. See
   the STACK note under „the giftwrap": the vertical band runs at 72 % of the
   card and crosses the title, the chip strip and the meta row, and undimmed
   brass (#a07f57) is 3.7:1 against white. Where the band covers a glyph the
   glyph is gone and no shadow helps; what this is for is the two EDGES, where
   white ink lands half on satin and half on the scrim and loses its outline in
   both directions at once.

   Navy rather than black, and the site's own navy: it is the colour the source
   contact sheet used for the same problem („Deviations", <scratchpad>/coupons/
   bows/notes.md) and the colour the offers' veil is made of, so the halo reads
   as depth rather than as a smudge. Two stops — a tight 2px drop that draws the
   outline and a 6px bloom that separates the run from the satin behind it.

   The „Dovanų kuponas" tag is deliberately not here: it is brown ink on a cream
   pill, so it carries its own ground across the band and a navy halo under
   brown-on-cream would only dirty it. */
/* THE SHADOWS ARE GONE. 2026-08-29, savininkas: „the use of box shadow in the
   dovanu kuponas is bad".

   He is right, and the two-stop navy halo above was treating a symptom. Type
   needs a glow only when it is sitting on something it cannot control; the
   answer is to give it a ground, not to outline every glyph. `.gf-bottom::before`
   below is that ground — a scrim sized to the TEXT rather than to a share of
   the frame, the same device the deal card uses (pp-offers.css, `.of-bottom::before`).

   One tight stop is kept, and only on the title, because the brass ribbon still
   passes behind it and a serif at 28px has strokes thin enough to disappear
   into satin. Everything else on this card now has a pill or a tile under it. */
.gf-title { text-shadow: 0 1px 3px rgb(8 28 43 / 55%); }

/* ---- the top row --------------------------------------------------------
   Only the tag lives up here. It is `flex-end` rather than `space-between`,
   because with one child left in the row space-between parks the tag on the
   LEFT. That is the same trap the „Plačiau" comment further down records; it
   has now been walked into twice.

   THE LEFT INSET IS THE RIGHT INSET, and that is the whole of the fix the
   client asked for on 2026-08-29: „why is text in these cupons moved a bit off
   the side?" It was `calc(var(--of-stub-w) + 20px)` — 83px at 1440 — because a
   coupon used to carry the same tear-off stub the offers do, and everything in
   the card had to start past it. The stub went earlier the same day („for gift
   cupons we dont need stubs") and the offset it existed to clear did not, so
   the type sat 63px in from a left edge with nothing on it, against a 20px
   right edge. There is no stub on this card at any width; there is therefore
   no reason for either row to be anything but symmetric. */
/* Left corner now: the rail owns the right edge of the card top to bottom. */
.gf-top {
  position: absolute;
  z-index: 3;
  top: 26px;
  left: 34px;
  right: 34px;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 12px;
  color: var(--colors-color-light);
}

/* The struck price, now a member of the meta line rather than a figure beside
   the price. `margin-left: auto` is deliberately NOT here: it belongs to
   „Plačiau", which is the only thing that gets pushed to the right edge, and a
   second auto margin would split the row in three.

   .68 is the offer card's own number for the same element (.of-was in
   pp-offers.css), and it is doing the work a size used to do: the struck figure
   and the validity beside it are now one style, body type, and the only thing
   that separates them is that this one is dimmer and has a line through it. */
/* TWO FAULTS IN ONE DECLARATION, both found by measuring the rendered page.

   The struck price moved INTO the h4 title („{title} — {price}") and started
   inheriting the display serif at 28.8px. Against `.gf-title` — Instrument Serif
   28.8px 400 — the only thing separating them was the tracking, −0.2px against
   −1px. That is precisely the near-duplicate pair the house rule exists to
   catch, and it was back in the gifts band.

   It is also what made „399 €450 €": `.gf-now` and `.gf-was` sat flush, gap
   measured at 0.00px, because nothing put space between two inline spans.

   So the old price is stated as body type rather than left to inherit, and it
   carries its own left margin. */
.gf-was {
  margin-left: 10px;
  font-family: var(--text-text-body-font-family, var(--font--primary));
  font-size: var(--text-text-body-font-size, 16px);
  line-height: var(--text-text-body-line-height, 26px);
  font-weight: 400;
  letter-spacing: var(--text-text-body-letter-spacing, -0.2px);
  opacity: .68;
}
/* THE PRICE IS THE STICKER. 2026-08-29, savininkas: „the cards being in the
   middle between contents in the gift cupon is also kinda weird."

   He is right, and moving the tiles would not have fixed it. The bottom of the
   coupon was carrying four things — a title, a price, a row of tiles and a
   validity line with a button on it — so whatever sat third was going to be
   „in the middle of" something. The fix is to take one out: the price goes to
   the red sticker the deal cards now wear, which is where the loudest number on
   a coupon belongs anyway, and the block underneath reads straight through —
   what it is, what is in it, how to get it.

   The sticker sits opposite the „Dovanų kuponas" tag rather than under it, and
   clear of the ribbon's vertical band. */
.gf-sticker { top: 18px; left: 20px; }
@media screen and (min-width: 861px) { .gf-sticker { top: 22px; } }

/* The tag sits in the slot a live deal fills with its countdown. Cream face,
   brown ink: the same badge idiom the announcement bar already uses, so it
   reads as this site's furniture rather than as a sticker. */
.gf-tag {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  background-color: var(--colors-color-bg-2);
  color: var(--colors-color-accent-2);
  white-space: nowrap;
}
.gf-tag svg { flex: 0 0 auto; opacity: .85; }

/* ---- the bottom -------------------------------------------------------- */
.gf-bottom {
  position: absolute;
  z-index: 2;
  /* Symmetric with the right inset — see the .gf-top note. The `calc(stub +
     20px)` that was here is the offset the deleted tear-off stub left behind,
     and it is why the client saw the type „moved a bit off the side". */
  /* „give a bit more paddings to the inner card so text is more moved from the
     sides." 20px was the offers card's gutter, carried over; a coupon is a
     present and wants more room round the edge of it. */
  left: 34px;
  right: 34px;
  bottom: 30px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  color: var(--colors-color-light);
}
/* THE SCRIM RADIATES FROM THE CORNER THE TEXT IS IN.

   2026-08-30, savininkas: „i think we can limit the text to take up to 50% of
   the card and the apply gradient outwar from bottom left corner of the card,
   not universally from the entire bottom."

   A linear band across the whole foot was darkening the right half of the
   photograph to protect type that is not there — and on this card the right half
   is where the rail is, so it was dimming the picture behind the frosted tiles
   as well. An ellipse anchored at 0% 100% covers the copy and lets the rest of
   the frame stay a photograph.

   It reaches past the card on both axes deliberately: the ellipse's edge must
   fall OUTSIDE the frame at the left and bottom, or the corner it is centred on
   gets a visible arc through it. */
.gf-bottom::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -140px;
  right: -34px;
  bottom: -30px;
  left: -34px;
  pointer-events: none;
  background-image: radial-gradient(
    128% 118% at 0% 100%,
    rgb(46 33 21 / 94%) 0%,
    rgb(46 33 21 / 80%) 34%,
    rgb(46 33 21 / 30%) 62%,
    rgb(46 33 21 / 0%) 82%
  );
}
.gf-title {
  display: block;
  color: var(--colors-color-light);
  text-wrap: balance;
}

/* ---- what is included, as one scrolling strip -------------------------
   2026-08-29, savininkas: „in the gift cupons maybe is also prepare lil cards
   with icons of what is included and put them in one scrollable row on the
   card". The inclusions used to live only behind „Plačiau"; they are the thing
   a buyer compares across cards, so they belong on the face of one.

   THE ROW SCROLLS, THE PAGE DOES NOT. Three separate rules do that and all
   three are load-bearing:

     `flex-wrap: nowrap` + `flex: 0 0 auto` on the chips is what creates the
       overflow in the first place — wrapping instead would grow the bottom
       block upwards until it walked through the title and out of the frame,
       which on a card that just lost a third of its height is one extra
       inclusion away.
     `overscroll-behavior-x: contain` stops the scroll CHAINING. Without it,
       flicking the strip to its end hands the rest of the gesture to the
       nearest scrollable ancestor, and on iOS that is the horizontal
       back-swipe: a guest reading the inclusions navigates away from the site.
     `overflow: hidden` on .gf-frame is the backstop. The strip is inside it, so
       even a mistake here cannot reach documentElement.scrollWidth.

   THE SCROLLBAR IS HIDDEN, THE SCROLLING IS NOT. Hiding it is not decoration —
   a native horizontal scrollbar rendered over a photograph, inside a card, on
   the platforms that draw them permanently, is a grey slab across the bottom of
   the artwork. Nothing here removes keyboard or trackpad access: the element is
   still a scroll container, so a two-finger swipe scrolls it, Chrome still
   makes it keyboard-reachable under its scrollable-region rule, and
   widgets/gifts.js adds mouse dragging on top because a mouse has no gesture
   for a scrollbar that is not there.

   THE FADE IS THE AFFORDANCE, and it is a mask rather than a gradient overlay
   because the strip must actually be transparent at its edge — the card behind
   it is a photograph, so anything painted on top in a fixed colour would be a
   smear rather than a fade. Both edges are driven by data-gf-more, which
   gifts.js recomputes from scrollWidth/scrollLeft, so a strip whose chips all
   fit has no fade at all. A permanently faded last chip on a card with two
   inclusions looks like a rendering fault, and that is what an unconditional
   mask-image gives you. With both custom properties at 0 the gradient's stops
   collapse and the mask is fully opaque — a no-op, not a near-miss. */
/* ================================================ kas kuponą sudaro ======
   2026-08-29, savininkas: „when I said to show off the benefits on dovanu
   kuponas card i imagined like a square rounded card with icon + title +
   subtitle, something cool and sexy."

   What was here: a single-line strip of pills that scrolled sideways, with a
   mask fading its ends, a ResizeObserver keeping that mask honest and a pointer
   drag so a mouse could push it. All of that to show three short labels — and
   it threw the interesting half of the data away. The engine sends each
   inclusion as `{title, subtitle}`: „Naktis dviviečiame kambaryje" / „su vaizdu
   į parką". The pill printed the title and dropped the subtitle.

   Tiles hold both, so the card stops listing what is included and starts
   arguing for it. Three of them, laid out on one row that wraps rather than
   scrolls — a row that scrolls hides its last item from everyone who does not
   think to push it. */
/* `.gf-tiles` is gone — the wrapper is `.gf-rail` now and the tiles live on a
   track inside it. The rule is left out rather than left behind. */
.gf-tile {
  flex: 1 1 0;
  min-width: 168px;
  max-width: 260px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  padding: 11px 14px 12px;
  border-radius: 14px;
  /* FLAT, NOT FROSTED. 2026-08-30, savininkas: „they are not visible on all bgs,
     so thats a problem… maybe lets make them flat color?"

     He is right and glass was the wrong instinct. A blur takes its legibility
     from whatever is behind it, so a tile over snow and a tile over a dark trunk
     are two different components — and the engine picks the photograph, not us.
     A fixed ground is the same tile on every cover. The colour is the coupon's
     own warm brown at 88 %, so it still reads as part of the card rather than as
     a panel dropped on it, and white on it is 9.4:1 whatever is underneath.

     The blur also cost a render surface per tile; with six on screen that was
     six of them. */
  /* FROSTED, LIGHT INK. „ok im hating the beige cards.. lets put back frosted
     glass with light text, fading in opacity in top and bottom."

     Third setting for this fill in one session — glass, then flat brown, then
     cream, now glass again — and the round trip was worth it, because the reason
     glass failed the first time was never the glass. It was that the fade at the
     ends of the column was a `mask`, a mask makes the element its own group, and
     a `backdrop-filter` inside a group has nothing behind it to sample. The
     tiles were frosting a blank. See `.gf-rail` for how the fade is done now. */
  background-color: rgb(255 255 255 / 14%);
  border: 1px solid rgb(255 255 255 / 22%);
  backdrop-filter: blur(12px) saturate(1.35);
  -webkit-backdrop-filter: blur(12px) saturate(1.35);
  color: var(--colors-color-light);
}
.gf-tile-ico {
  width: 20px;
  height: 20px;
  opacity: .82;
}
.gf-tile-ico svg { display: block; width: 100%; height: 100%; color: inherit; }
/* NOT CAPS. „why are you using caps for the lil cards with whats included, i
   hate it."

   They were caps because that is the card's label style and reusing it kept
   the type budget at three. But „NAKTIS DVIVIETIAME KAMBARYJE" set at 12px
   with 3px of tracking is a filing-cabinet label, and it wraps to three lines
   in a tile that is 132px wide — caps have no descenders and no word shape, so
   there is nothing for the eye to catch on.

   Both lines are the card's BODY type now, and they are told apart the way the
   house rule says to: colour, not size. Title at full strength, subtitle at
   62 %. One tuple, two jobs, and the tile still reads at a glance. */
/* „the text within the cards has too big line height for me." It was inheriting
   the body's 26px on a 16px face — right for a paragraph, far too airy for a
   two-word label in a box. */
.gf-tile-t {
  line-height: 1.25;
  letter-spacing: var(--text-text-body-letter-spacing, -0.2px);
  text-wrap: balance;
}
/* „when they have a description, it should be closer to the title and smaller."
   The two lines were the same 16px separated by the tile's 6px gap, which read as
   two facts rather than as a thing and its qualifier. The site's own small-text
   token, pulled up tight under the title. */
.gf-tile-s {
  margin-top: 1px;
  font-size: var(--text-text-small-font-size, 13px);
  line-height: 1.3;
  letter-spacing: var(--text-text-body-letter-spacing, -0.2px);
  opacity: .62;
  text-wrap: balance;
}
/* ============================== TWO COLUMNS, AND NO RIBBON ==============
   2026-08-30, savininkas: „from the gift cupons, remove the bows ig… and then
   lets put the feature cards on the right side?" and „dovanu kuponai dont need
   the red badges."

   All three notes are the same note. The coupon was carrying a gold ribbon, a
   bow, a red sticker, a cream tag, a title, a blurb, a price, three tiles and a
   validity line — nine things on one photograph, and every one of them needed a
   scrim or a shadow to survive the two above it. Taking the ribbon and the
   sticker off does more than remove two objects: it gives the copy the whole
   frame back, so the block can be a plain two-column layout with the words on
   the left and what is included on the right, and nothing has to be defended
   from anything.

   The bow is not deleted from the codebase — `BOW` and `.gf-ribbon` stay in
   widgets/gifts.js and below, unreferenced. It was a whole afternoon's work with
   Magnific and it is the sort of thing that comes back. */
.gf-bottom {
  flex-direction: row;
  align-items: flex-end;
  gap: 26px;
}
/* Half the card, and no more. Beyond that the copy runs under the rail. */
.gf-main {
  flex: 0 1 auto;
  width: 50%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
/* THE RAIL: A FULL-HEIGHT WINDOW WITH THE TILES GOING ROUND INSIDE IT.

   „they should be full height of the card (move dovanu kuponas chip to other
   side)". So it is no longer a column inside the bottom block — it is its own
   strip down the right of the frame, floor to ceiling, and the tag moved to the
   left corner to get out of its way.

   The track rises by exactly half its own height and starts again. The track is
   the same run twice, so at −50 % the second copy is sitting where the first one
   started and the seam cannot be seen. Duration scales with the number of tiles
   in a turn, so three inclusions and six move at the same SPEED rather than in
   the same period.

   THE FADE IS AN OVERLAY, NOT A MASK, and that is the fix for „the blur is not
   working". `mask-image` on this element made it a group of its own, and a
   `backdrop-filter` inside a masked group has nothing behind it to sample — the
   tiles were frosting a blank. Two gradient overlays in the card's own scrim
   colour do the same job from on top, and leave the backdrop alone. */
/* The rail is outside `.gf-bottom` now, so it no longer inherits that block's
   light ink — it inherits the frame's, which is the page's dark. Stated here. */
.gf-rail {
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  right: 0;
  width: min(38%, 268px);
  padding: 0 26px 0 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  pointer-events: none;
  color: var(--colors-color-light);
}
/* The mask that hides the button's second label is sized from the type it was
   built for; shrinking the label leaves the duplicate peeking out below it as a
   stray „--". Height and leading move with the size. */
.dl-modal .dl-modal-cta .button-text-mask {
  height: 19px;
}
.dl-modal .dl-modal-cta .button-text,
.dl-modal .dl-modal-cta .button-text-small {
  line-height: 19px;
}

/* ONE RUN OF CAPITALS IN THE POPUP, NOT TWO.
   „i also wanna see clean layout with not 100000 different font sizes..."

   Measured inside the open dialog: the eyebrow was Instrument Sans 12/700/3px
   and the button's label was Instrument Sans 14/700/2px. Two pixels and one
   notch of tracking apart — the exact pair the house rule names, sitting in the
   same box. The button is a site-wide component and exempt on paper, but the
   exemption is for type the SECTION did not introduce, and a popup that carries
   two caps styles reads as a mish-mash whatever the rule says.

   Scoped to these dialogs rather than changed globally: `.cta-main` is on every
   page of the site and re-cutting it from here is not this file's business. */
.dl-modal .dl-modal-cta .button-text,
.dl-modal .dl-modal-cta .button-text-small {
  font-size: var(--text-label-font-size, 12px);
  letter-spacing: var(--text-label-letter-spacing);
  font-weight: var(--text-label-font-weight);
}

/* THE SAME TILES IN THE POPUP, LAID OUT AND STILL.

   „i wanna see the same cards, just layed out nicely not moving. i also wanna
   see clean layout with not 100000 different font sizes..."

   Same `.gf-tile` as the rail — one component, two arrangements. In here there
   is no window to fit inside, so nothing is truncated and nothing moves: every
   inclusion, on a grid that reflows from two columns to one.

   The popup's ground is the site's paper, not a photograph, so the glass has
   nothing to frost. It takes the flat cream and the brown ink the „Dovanų
   kuponas" tag uses — the same pair, one surface each. */
/* TWO COLUMNS, STATED. „cards should be 2x2."
   `auto-fit` with a 190px floor should have given two of them in a 470px body
   and gave one, because `.gf-tile` carries `min-width: 168px` from the rail and
   an item's minimum wins over the track's — so each track resolved wider than
   the floor and only one fitted. Asking for two columns is both shorter and the
   thing that was actually wanted. */
.gf-tiles-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  /* Full bleed of the popup's text column. The running text above and below is
     held to a 30em measure; the tiles are not running text and take the width. */
  width: 100%;
  margin: 2px 0 0;
}
@media screen and (max-width: 479px) {
  .gf-tiles-grid { grid-template-columns: minmax(0, 1fr); }
}
/* GLASS IN HERE TOO. „cards should be frosted glass."

   Worth being straight about what that can mean on this surface: the popup's
   ground is flat paper, so a `backdrop-filter` has nothing behind it to blur —
   the blur is declared, it runs, and it samples one flat colour. What makes the
   tile read as glass here is the rest of the recipe: a translucent fill rather
   than a solid one, a hairline that catches like an edge, and the ground showing
   through. Ink stays brown, because white on paper is not readable and matching
   the card's INK would cost the thing the card's tile is actually for. */
.gf-tiles-grid .gf-tile {
  width: auto;
  max-width: none;
  /* The rail's 168px floor would keep a two-column track from ever resolving. */
  min-width: 0;
  flex: none;
  /* A TINT, NOT A TRANSLUCENT WHITE. The fill used to be white at 58 %, which
     needed the panel below it to be visible at all — white on white is white.
     With the panel gone the tile has to carry its own contrast, so the same
     translucency is stated in the coupon's brown instead: still see-through,
     still hairlined, but it reads on the popup's bare paper. */
  background-color: color-mix(in srgb, var(--colors-color-accent-2) 6%, transparent);
  border-color: color-mix(in srgb, var(--colors-color-accent-2) 15%, transparent);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  /* The inset white highlight was catching an edge against the tinted panel.
     On white paper it is white on white — an invisible declaration that only
     costs a paint. */
  box-shadow: none;
  color: var(--colors-color-accent-2);
  padding: 13px 15px 14px;
}
.gf-tiles-grid .gf-tile-ico { opacity: .55; }
/* ONE BODY SIZE IN THE POPUP, INCLUDING INSIDE THE TILES.
   `.gf-tile-s` is 12px on the CARD, where it is a qualifier whispered under a
   title on a photograph and the card's own budget already counts it. Measured
   in the open dialog it was a FOURTH tuple — Instrument Sans 12/400 sitting
   under Instrument Sans 16/400, near-duplicates that read as a mistake rather
   than as a hierarchy. In here it joins the popup's body and is told apart the
   way the house rule says to: by colour. Scoped to `.gf-tiles-grid`, which
   exists only in the dialog, so the card is untouched. */
.gf-tiles-grid .gf-tile-s {
  font-size: inherit;
  line-height: 1.35;
  margin-top: 2px;
}

/* WAS: a tinted panel the glass sat on. „the cards should not be in special
   area" — 2026-08-30, savininkas. It was there because a white-at-58 % tile
   needs something behind it; the tile carries its own tint now (above), so the
   panel has nothing left to do but draw a box around a group that was already
   a group. The tiles stand on the popup's own ground. */

/* NO MASK ON THE RAIL, AND THIS TIME IT IS MEASURED.

   „the cards are not blurred." He is right, and I had written the opposite into
   this file twice — first „a mask kills the blur", then, after a bad test,
   „tested properly: the blur is live". The second note was wrong.

   Measured 2026-08-30 on a real tile, 230x58 CSS px captured at dsf 2, roll
   frozen, four states compared pixel for pixel:

     as shipped (mask on, backdrop-filter on)   =  identical to blur OFF, 0/53360 px
     mask removed (backdrop-filter on)          =  90 % of pixels changed,
                                                   mean delta 20.3, max 130
     edge energy inside the tile                =  18.5 with the mask, 10.6 without

   Zero pixels. The `backdrop-filter` was not weak, it was doing NOTHING: a
   masked element is a backdrop root, the rail paints no background of its own,
   so every tile inside it was blurring an empty surface. Removing the mask is
   what turns the frost on.

   SO THERE IS NO FADE AT THE ENDS, and it cannot come back as a mask.
   „fading in opacity in top and bottom" and „put back frosted glass" are the
   same sentence, and in CSS they are exclusive: over a photograph, the only way
   to fade an element out is to mask it, and masking it is what blanks the
   backdrop. The frost is the thing that was asked for twice, so the frost wins.
   The rail runs floor to ceiling of the frame, so its ends ARE the card's edges
   — which is the other thing that was asked for: „lets make the cards not cut
   by the gradient - just have them be cut by edges of the card." */


/* WAS: no fade at the ends. „lets make the cards not cut by the gradient - just have
   them be cut by edges of the card."

   There were two gradient overlays here softening the tiles where the window
   clips them. They are gone: the rail runs the full height of the frame, so its
   edges ARE the card's edges, and a tile meeting the edge of a card is a tile
   going off the edge of a card. Fading it was solving a problem the full-height
   rail had already solved — the fade only ever made sense while the column was a
   196px box floating in the middle of the picture. */

.gf-tiles-track {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
  will-change: transform;
}
.gf-tiles-dup { display: contents; }
.gf-tiles-track > .gf-tile,
.gf-tiles-dup > .gf-tile { width: 100%; max-width: none; min-width: 0; }
@media (prefers-reduced-motion: no-preference) {
  .gf-tiles-track {
    /* 3.4s a tile, so a longer list takes longer rather than moving faster. */
    animation: gf-roll calc(var(--gf-loop-n, 3) * 3.4s) linear infinite;
  }
  /* NO PAUSE ON HOVER. „cards should nto stop spinning on hover."
     It paused so a reader could finish an inclusion they were halfway through —
     but the whole card is one button, so the pointer is on it for the entire
     approach to the click, and the roll stopping under the cursor read as the
     card breaking rather than as a courtesy. The full list is in the popup that
     click opens; nobody has to read it off a moving strip. */
}
@keyframes gf-roll {
  from { transform: translateY(0); }
  to { transform: translateY(calc(-50% - 4px)); }
}

@media screen and (max-width: 860px) {
  /* A 2:1 coupon on a phone is 355x178 — there is no room in it for a column of
     tiles beside two lines of copy, which is why the first attempt had the rail
     lying across the photograph on top of the tag. The frame goes portrait
     instead and keeps the same anatomy: copy bottom-left, rail down the right. */
  .gf-card .gf-frame { aspect-ratio: 4 / 5; }
  .gf-bottom { left: 22px; right: 22px; bottom: 22px; }
  .gf-bottom::before { left: -22px; right: -22px; bottom: -22px; top: -120px; }
  .gf-main { width: 62%; }
  .gf-rail { width: 40%; padding-right: 16px; }
  .gf-top { top: 20px; left: 22px; right: 22px; }
}

/* WAS: the content kept clear of the ribbon's vertical band.

   The band runs the full height at `--gf-cross-x`, and it is drawn OVER the
   copy on purpose — the client asked for the bow on top of everything. That was
   survivable while the bottom of the card held a title and two short rows; it
   is not survivable now that it holds a title, a price, three tiles and a meta
   line, and the render showed the title struck through by the horizontal band
   and the third tile sliced by the vertical one.

   Two moves, no compromise on the bow: the block stops short of the vertical
   band, and the horizontal crossing is raised above where the block begins.
   The rule already existed for phones, where the crossing sits further left;
   it is simply not a phone-only problem. */
/* The two rules that held the block clear of the band are gone with the band. */
/* „+1 dar įskaičiuota", on the thin row rather than as a fourth tile. */
.gf-plus { opacity: .62; letter-spacing: var(--text-text-body-letter-spacing, -0.2px); }

@media screen and (max-width: 767px) {
  .gf-tile { min-width: 100%; padding: 10px 12px 11px; }
  .gf-tiles { gap: 6px; }
}


/* Its own ground, and that is the contrast argument. The veil over the bottom
   of the card is roughly half-strength this far up, so a chip with no ground
   would be putting 12px caps straight onto a room photograph. Brown at 55 %
   over that veil resolves to about #735a3d, which carries the white label at
   6.4:1 — and it is the veil's own colour, so the chips read as part of the
   scrim rather than as five white boxes dropped on the picture. It is also
   what keeps the chips legible where the brass ribbon passes behind them. */
.gf-chip {
  flex: 0 0 auto;
  /* Never wider than the strip, so a single very long inclusion ellipsises
     instead of hiding every chip after it behind one unscrollable slab. */
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px 6px 9px;
  border-radius: 999px;
  background-color: rgb(79 59 40 / 55%);
  border: 1px solid rgb(255 255 255 / 18%);
}

/* The icons are inlined by widgets/gifts.js, which explains at length why they
   are markup rather than <img> and why --ico-cut is deliberately absent. This
   is the backstop it mentions: every file in public/images/pp-icons/ carries
   `color="#9e8261"` on its root, and a presentation attribute is beaten by any
   CSS declaration at all, so a drawing pasted in later with the attribute still
   attached cannot quietly go brown on a brown chip. */
.gf-chip-ico {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  opacity: .8;
}
.gf-chip-ico svg { display: block; width: 100%; height: 100%; color: inherit; }

/* min-width: 0 is not tidying. .gf-chip is a row flex container, the automatic
   minimum size applies along its main axis, and without this the label refuses
   to shrink below its content width — so max-width on the chip is ignored, the
   ellipsis never appears, and one long inclusion is as wide as it likes. */
.gf-chip-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* One thin row: how long it is good for, and the way in. Quiet on purpose —
   the validity is a fact about the coupon, not the argument for it, and the
   equivalent row on a deal card is a clock precisely because there the fact IS
   the argument. */
.gf-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
}
/* Same collapse as .of-when on the deal card: this was the only thing in the
   band still setting Instrument Sans 16/400 at the browser's default tracking,
   half a notch off the body copy beside it. */
.gf-valid {
  opacity: .82;
  white-space: nowrap;
  letter-spacing: var(--text-text-body-letter-spacing, -0.2px);
}

/* Pushed right rather than held apart by `justify-content: space-between`,
   because a package with no validity_months renders no .gf-valid at all and
   space-between would then park „Plačiau" on the LEFT, where nothing else on
   this page puts it. */
.gf-more {
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid rgb(255 255 255 / 34%);
  color: var(--colors-color-light);
  white-space: nowrap;
  transition: background-color .25s ease, color .25s ease, border-color .25s ease;
}
.gf-more::after {
  content: "";
  width: 5px;
  height: 5px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-1px) rotate(-45deg);
  transition: transform .25s ease;
}
/* Fills with brown on hover where the deal pill fills with navy-on-white —
   the last of the temperature cues, and the one a guest sees while their
   cursor is already on the card they are about to open. */
.gf-card:hover .gf-more {
  background-color: var(--colors-color-bg-2);
  color: var(--colors-color-accent-2);
  border-color: transparent;
}
.gf-card:hover .gf-more::after { transform: translate(3px, -1px) rotate(-45deg); }

.gf-card:focus-visible {
  outline: 2px solid var(--colors-color-accent-1);
  outline-offset: 4px;
  border-radius: var(--spacing-radius-main, 16px);
}

@media screen and (max-width: 991px) {
  [data-gifts-list] { gap: 16px; }
  /* The old `.gf-now { font-size: … }` and `.gf-was { font-size: … }` that
     lived here are gone on purpose, and nothing may replace them. The card
     carries exactly three type styles and they are the offer card's three (see
     the note at the top of this sheet); a size re-stated at one breakpoint is a
     FOURTH style on phones only, which is precisely how the mish-mash got in
     the first time. The three responsive scales the card follows — .text-h4,
     .label and the body — already step down here on their own. */
  .gf-frame { --gf-band: 20px; }
}
@media screen and (max-width: 767px) {
  [data-gifts-list] { grid-template-columns: minmax(0, 1fr); }
  /* 8:5 is right in a row and too shallow alone on a phone: a full-width card
     at 8:5 leaves the title, the chip strip and the meta row stacked in about
     90px. 4:3 buys back the height the bottom block needs, and still keeps the
     next card's edge on screen — which is what tells a thumb there is more than
     one gift. The number matches pp-offers.css. */
  .gf-frame { aspect-ratio: 4 / 3; }
  /* Symmetric here too. This block is where the stale stub offset would have
     won on source order after the rules above were fixed — the same way a
     leftover `left: 16px` in pp-offers.css once painted the stub over the first
     three characters of a title on a phone. Both edges are stated together so
     the pair can never drift again. */
  .gf-top { top: 14px; left: 16px; right: 16px; }
  .gf-bottom { left: 16px; right: 16px; bottom: 14px; }
  .gf-tag { padding: 5px 10px; }
  /* The bow rides UP on a phone, it does not shrink out of the way. A
     full-width 4:3 card puts the title block much higher than a card in a row
     does, so 36 % of the height is no longer empty — it is where the title
     starts. 28 % is the strip that is still clear between the tag and the
     title, and the bow's tails, which hang below the knot, now stop above it.
     Bow moves, title does not. */
  .gf-frame { --gf-band: 16px; --gf-cross-x: 68%; --gf-cross-y: 38%; --gf-bow-w: clamp(104px, 38%, 160px); }
  .gf-chips { --gf-fade: 22px; gap: 5px; }
  .gf-chip { padding: 5px 10px 5px 8px; gap: 6px; }
}

/* ------------------------------------------- gift rows in the dialog ----
   The .dl-modal shell, the close button, the list and the CTA are all shared
   with the offers (prie-parko.css). Only what is peculiar to a coupon is here:
   the price restated where the decision is actually made, and the line that
   says what a coupon IS.

   ================================ THE DRAWER ITSELF ====================
   2026-08-30, savininkas: „to give them more space expand the whole drawer so
   its not crammed".

   The shared shell is `min(485px, 100% - 32px)`, which left a 421px text
   column — and into it went a heading with the price welded on (it filled the
   line edge to edge), a two-column tile grid at 196px a track, and a
   two-column form at 205px a field. Everything in the popup was at its
   minimum at once.

   Widened HERE and not in prie-parko.css: `.dl-modal` is also the live
   offers' popup, which holds a paragraph and a list and does not need the
   room. The attribute selector is a shade more specific than the shared
   `.dl-modal` class, so this wins regardless of which sheet the head loads
   first — and that is also why the phone width has to be re-stated below
   rather than left to the shared 767px rule, which would now lose. */
.dl-modal[data-gift-dialog] {
  width: min(640px, calc(100% - 32px));
}
[data-gift-dialog] .dl-modal-body {
  padding: 56px 40px 40px;
  gap: 12px;
}
@media screen and (max-width: 767px) {
  .dl-modal[data-gift-dialog] { width: calc(100% - 16px); }
  [data-gift-dialog] .dl-modal-body { padding: 48px 22px 28px; }
}

/* THE WIDTH IS FOR THE TILES AND THE FORM, NOT FOR THE PROSE.
   A 560px column of 16px Instrument Sans measures 78 characters a line, which
   is at the far edge of what a reader tracks without losing the return sweep.
   Running text is held to 30em — 480px, ~66 characters — and the grid and the
   form take the whole column. Measured, not guessed: the face averages 7.2px a
   character at this size, so 480/7.2 = 66.7. */
[data-gift-dialog] .dl-modal-summary,
[data-gift-dialog] .gf-note,
[data-gift-dialog] .gf-buy-note,
[data-gift-dialog] .gf-buy-err {
  max-width: 30em;
}

/* THE TITLE IS BIGGER. „title could be bigger."
   `.text-h4` resolves to clamp(27px, 2vw, 36px) — 28.8px on a 1440 screen,
   because 2vw is a fraction of the WINDOW and this heading lives in a 640px
   drawer that does not grow with it. The drawer's own step is stated here, and
   the price takes the identical declaration below: one serif tuple, two jobs.
   Change one and you must change the other, which is why they share a custom
   property rather than two copies of a number. */
[data-gift-dialog] { --gf-dlg-serif: 36px; }
@media screen and (max-width: 767px) {
  [data-gift-dialog] { --gf-dlg-serif: 30px; }
}
[data-gift-dialog] .dl-modal-body > h2,
[data-gift-dialog] .gf-modal-price .gf-now {
  font-family: var(--text-h4-font-family);
  font-size: var(--gf-dlg-serif);
  line-height: 1.08;
  font-weight: var(--text-h4-font-weight);
  letter-spacing: var(--text-h4-letter-spacing);
}
/* Third of the four blocks, so it gets the air that says a new one has begun:
   the body's 12px gap plus this. */
[data-gift-dialog] .gf-modal-price { margin-top: 10px; }

.gf-modal-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 4px 0 0;
}
/* THE GAP IS STATED HERE, ONCE. `.gf-was` carries `margin-left: 10px` for the
   CARD, where the two figures are two inline boxes in a heading and nothing
   else would separate them. In this flex row the margin ADDS to the gap, so
   the popup would space its price differently from the card by whatever the
   card's margin happened to be that week. Zeroed, and the row's own gap is the
   whole answer: 14px between „399 €" and „450 €", measured. */
.gf-modal-price .gf-was { margin-left: 0; }
/* The full .text-h4 token set, not three quarters of it. This used to name the
   family and the size and let the weight, the tracking and the line-height fall
   through from .dl-modal-body — which produced a face that LOOKED like the
   heading two lines above it and measured as a separate style, and „looks the
   same, measures different" is the whole of what the client was seeing when
   they asked „why is this a font mish mash?". The price and the title of the
   coupon are literally one style; inside a gift dialog the pair is declared
   together above, off `--gf-dlg-serif`. This is the fallback for any other
   surface that ever renders `.gf-modal-price`. */
.gf-modal-price .gf-now {
  font-family: var(--text-h4-font-family);
  font-size: var(--text-h4-font-size, 36px);
  line-height: var(--text-h4-line-height);
  font-weight: var(--text-h4-font-weight);
  letter-spacing: var(--text-h4-letter-spacing);
}
/* Size and face are the dialog's own 16px body now, inherited: .gf-was left the
   caps rule when the card's meta line went to body type (see „the card's three
   type styles" at the top of this sheet), and in here that lands it on the same
   style as the summary and the inclusions rather than on a fourth one. Only
   what changes between a photograph and a cream popup is set here: full opacity
   against a light ground, ink instead of white, and the text-shadow that holds
   the figure off a bright room turned off. */
.gf-modal-price .gf-was {
  opacity: 1;
  text-shadow: none;
  color: color-mix(in srgb, var(--colors-color-dark) 55%, transparent);
}
/* Accent, not grey. This one line is the entire explanation of how a gift
   differs from everything else on the page — bought now, redeemed later, by
   somebody who has not chosen their dates — so it is the one line in the popup
   that is allowed to be coloured.

   Two classes rather than !important: .dl-modal-dates in prie-parko.css sets a
   muted grey on the same element, and that sheet happens to load first — but
   „happens to" is not a rule anybody can see from here, and a head reordered
   for a performance reason would silently grey this line out. */
/* The validity note: the popup's body style, in the muted ink. It used to be
   `label-small` — see the note in widgets/gifts.js for why capitals were right
   then and are not now. */
/* Directly under the price, which is the thing it qualifies: the term of the
   coupon, not a fourth heading. The popup's flex gap is the whole spacing. */
.gf-note {
  margin: 0;
  color: color-mix(in srgb, var(--colors-color-dark) 62%, transparent);
}
.gf-sub { opacity: .64; }

/* ------------------------------------------------- kaina ant kortelės ----
   Kuponas — daiktas, kurį perka, todėl kaina yra ant kortelės, o ne už
   „Plačiau". Serifas, tas pats stilius kaip antraštės: trys stiliai išlieka
   trys. Perbraukta įprasta kaina lieka body stiliaus ir prigesinta spalva. */
.gf-card-price {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  white-space: nowrap;
}
.gf-card-price:empty { display: none; }
.gf-meta .gf-now { line-height: 1; }

/* ------------------------------------------------ siaurame ekrane ----
   Juosta yra VIRŠ teksto (savininko prašymu: „They should be on top of
   everything"), todėl ties 767 ir siauriau ji nukirsdavo „PLAČIAU" į „LAČIAU",
   paskutinį ženkliuką ir patį užrašą „Dovanų kuponas". Sprendimas ne nuleisti
   juostą atgal po tekstu, o baigti tekstą prieš ją: abu blokai gauna dešinįjį
   atitraukimą, apskaičiuotą iš pačios juostos padėties, todėl jie negali
   persidengti nepriklausomai nuo to, kur ta juosta stovi. */
@media screen and (max-width: 767px) {
  /* Vertikali juosta EINA per tekstą, kaip ir plačiame ekrane — savininkas
     prašė juostos virš visko, o 16 px juosta su navy šešėliu po raidėmis to
     nepaverčia neįskaitomu (išmatuota: 4,57:1 blogiausiu atveju). Bandymas
     baigti tekstą prieš ją paliko ženkliukams 201 px iš 358 ir jie beveik visi
     iškeliavo į šoninį slinkimą — kaina didesnė už problemą.

     HORIZONTALI juosta — kita byla. Ji eina per visą plotį, tad nuo jos
     pasitraukti neįmanoma, o telefone antraštė laužiasi į dvi eilutes ir
     užauga į ją: „Naktis dviem" atsidūrė PO satinu, ne ant jo. Todėl kryžius
     kyla į 26 % — virš antraštės bloko, žemiau ženkliuko „Dovanų kuponas“. */
  .gf-frame { --gf-cross-y: 26%; }

  /* Ir dar vienas skirtumas, kurio nematyti iš taisyklės, o tik iš ekrano:
     juosta gali eiti per ANTRAŠTĘ — didelės serifo raidės su navy šešėliu po
     satinu skaitosi kaip kaspinas ant užrašo, būtent to ir prašyta. Bet ji
     negali eiti per PILIULES — ženkliuką „Dovanų kuponas", įskaičiuotų dalykų
     ženkliukus ir „Plačiau". Juosta nukerta jų rėmelį ir pirmą raidę, ir tai
     skaitosi ne kaip kaspinas, o kaip piešimo klaida: „PLAČIAU" virsta
     „LAČIAU". Todėl piliulės baigiasi prieš juostą, o antraštė — ne. */
  .gf-top,
  .gf-chips,
  .gf-meta {
    margin-right: calc(100% - var(--gf-cross-x) + var(--gf-band));
  }
  .gf-top { right: auto; left: 16px; }
}

/* Variantas B (lygi kremo spalva, nuotrauka dešinėje) buvo parodytas šalia A
   ir atmestas: „i prefer the card that is full image." Taisyklės išimtos kartu
   su juo — liko tik ši eilutė, kad kitas žmogus nepradėtų jo iš naujo. */
.gf-card { width: 100%; }

/* ============================================ perkant dovanų kuponą =====
   2026-08-30, savininkas: „the gift cupons ppl should be supposed to buy
   outright, not date needed right? So why you drop them to date picker?"

   Kuponas neturi datos — ją renkasi tas, kam dovanojama, po kelių mėnesių. Todėl
   mygtukas nebeveda į /rezervacija/ (ten kalendorius), o čia pat surenka keturis
   laukus ir perduoda apmokėjimui. Laukų stiliai — svetainės formų, ne nauji. */
.gf-buy {
  /* The fourth block. „Kam ir nuo ko" is a new subject, so it starts further
     down the page than the popup's 12px rhythm — 12 + 8. */
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.gf-buy-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 16px;
}
@media screen and (max-width: 479px) {
  .gf-buy-grid { grid-template-columns: minmax(0, 1fr); }
}
.gf-buy-f { display: flex; flex-direction: column; gap: 6px; }
/* WAS: the card's uppercase label style, „the same as KAS ĮSKAIČIUOTA".
   2026-08-30, savininkas: „why are fonts so bold".

   Measured in the open dialog, the caps tuple — Instrument Sans 12/700 with
   3px of tracking — was carrying TEN runs of text: the eyebrow, two section
   headings, the button, and these five field labels. Five of the ten were
   labels on input boxes, which is four more shouts than any form needs; the
   site's own booking card had already worked this out and un-shouted its
   labels for exactly the reason stated there — „over four form fields in a
   small card it reads as four competing headings" (prie-parko.css,
   `.form-book .input-wrap-contact > .label`).

   They join the popup's body style rather than inventing the booking card's
   13px, which would have been a fourth tuple in here. Told apart from the
   answer the guest types by colour, which is what the house rule says to do
   instead of reaching for a size. */
.gf-buy-l {
  font-family: var(--text-text-body-font-family, var(--font--main));
  font-size: var(--text-text-body-font-size, 16px);
  line-height: var(--text-text-body-line-height, 150%);
  font-weight: var(--text-text-body-font-weight, 400);
  letter-spacing: var(--text-text-body-letter-spacing, -0.2px);
  text-transform: none;
  color: color-mix(in srgb, var(--colors-color-dark) 58%, transparent);
}
/* THE SITE'S FIELD, NOT A BIGGER ONE. „why are inputs so huge."

   The bare `.text-field` is `padding: 16px` with no line-height of its own,
   which measured 58px tall — and `.text-field.textarea` is a flat
   `height: 136px`, so the „Linkėjimai" box alone was a fifth of the drawer.
   The site's enquiry form on /renginiams/ (`.uz2-input`) is 50px: 12px/16px of
   padding on a 24px line, 8px radius. That is the number this form takes,
   arrived at the same way — padding + line-height + border — rather than
   hard-coded, so it tracks the body token if that ever moves. The textarea
   loses the fixed height and is sized by its `rows`, which is the only place
   the number should live. */
/* THE FIELD IS THE SITE'S FIELD, BORDER INCLUDED — which it was not.

   Measured after the first pass: the height, the padding and the radius had all
   been brought into line with `.uz2-input` on /renginiams/, and the BORDER had
   not. It was still the Webflow template's `.text-field`:

     gift form   1px DASHED  rgb(8 28 43 / 48%)   no fill
     the site    1px solid   rgb(8 28 43 /  8%)   8% fill, 48% only on focus

   A dashed rule at half strength is what a drop zone looks like, or a field
   that has failed validation — and 48% is the site's FOCUS colour, so every
   resting field was drawn as if it were the active one. The site's own field is
   a filled well with a whisper of an edge; this is that, stated here rather than
   inherited, because the template class fights back. */
.gf-buy .text-field {
  width: 100%;
  margin: 0;
  padding: 12px 16px;
  border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--colors-color-dark, #081c2b) 8%, transparent);
  background-color: color-mix(in srgb, var(--colors-color-dark, #081c2b) 8%, transparent);
  color: var(--colors-color-dark, #081c2b);
  outline: none;
  transition: border-color .2s;
  font-size: var(--text-text-body-font-size, 16px);
  line-height: var(--text-text-body-line-height, 150%);
}
.gf-buy .text-field::placeholder {
  color: color-mix(in srgb, var(--colors-color-dark, #081c2b) 52%, transparent);
}
.gf-buy .text-field:focus {
  border-color: color-mix(in srgb, var(--colors-color-dark, #081c2b) 48%, transparent);
}
.gf-buy .text-field.textarea {
  height: auto;
  resize: vertical;
}
.gf-buy-note {
  margin: 2px 0 0;
  color: color-mix(in srgb, var(--colors-color-dark) 62%, transparent);
}
.gf-buy-err {
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  background-color: rgb(168 50 31 / 10%);
  color: #8f2a19;
}
.gf-buy-err[hidden] { display: none; }
/* The mask clips the button's second label — the hover copy — and it does that
   with `overflow: hidden` on a 22px BOX. Here the markup is spans, because the
   whole thing lives inside a <form> and a <div> in a <button> is not phrasing
   content; an inline span has no height and clips nothing, so both labels
   printed side by side: „PIRKTI DOVANĄ — 129 € PIRKTI DOVANĄ — 129 €". */
.gf-buy-go { margin-top: 4px; align-self: flex-start; }
.gf-buy-go .button-text-mask { display: block; height: 19px; overflow: hidden; }
.gf-buy-go .button-text { display: block; line-height: 19px; }
.gf-buy-go[disabled] { opacity: .55; pointer-events: none; }
/* Kol vyksta užklausa — kad nespaustų antrą kartą ir nenusipirktų dviejų. */
.gf-buy[data-busy] { opacity: .7; }
