/* =====================================================================
   ROUND 86 -- THE ADVERTISEMENT BOX, AND THE TWO STICKY UNITS.

   Reached only through `.ttc-ad`, which app/adboxes.box() emits and which is
   emitted only when `ad_slots_live` is ON **and** the slot's own row says
   `enabled = 1`. Off, there is no element on the page and not one declaration
   in this file matches anything.

   THE NUMBERS BELOW WERE MEASURED ON THE CANDIDATE, six page types, eleven
   widths, before a line of this was written:

       width    #main-right (newsletter)   floating Comments/Share bar
       <=1200   display:none               RIGHT, 42-79.2px
       1201     x868    w303               RIGHT x1121.8..1201  <- ON the rail
       1280     x947    w303               RIGHT x1200.8..1280  <- ON the rail
       1366     x1021   w303               RIGHT x1286.8..1366  <- ON the rail
       >=1400   x1038   w303               LEFT  x0..79.2       <- rail clear

   ROUND 86b (d) CLOSED THE MIDDLE BAND. The bar's breakpoints now sit on the
   rail's own edge -- RIGHT to 1200, LEFT from 1201 -- so the sign-up and the
   bar are never on the same side. recipe-v3-floating-bar.css carries the rule
   and the measurement; this file no longer has to work around it.

   Two things follow and both are load-bearing:
     1. the sticky sidebar is >=1201 ONLY -- the width at which the rail
        itself appears. ROUND 94 moved it there from 1400. 86b's note said the
        1201..1399 band was already clear of the floating bar and that the unit
        could run from 1201, and left the number alone because nothing had asked
        it to move; round 94's review asked, because at 1280 and 1366 the unit
        was in the markup and invisible. See the long note above the rule.
     2. the sidebar lives INSIDE the rail, under the newsletter box, at the
        rail's own width. It cannot narrow the rail or overlap it, because it
        is a block in the same column rather than anything positioned.
   ===================================================================== */

/* ---- THE RESERVED HEIGHT, WHICH IS THE WHOLE POINT ----------------------
   `--adh-d` / `--adh-m` come from the slot's row and are written onto the
   element by app/adboxes.box(). They become a min-height, so the space is
   held open BEFORE the fill arrives and the page does not move when it lands.
   A box with no creative and `collapse` set is never emitted at all, so an
   empty reserved frame is not a state this can be in. */
.ttc-ad {
  min-height: var(--adh-m, 250px);
  margin: 24px 0;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  overflow: hidden;
  /* never wider than the column it is in, at any breakpoint */
  max-width: 100%;
}
@media (min-width: 768px) {
  .ttc-ad { min-height: var(--adh-d, 250px); }
}

.ttc-ad__in {
  display: flex; align-items: center; justify-content: center;
  width: 100%; flex: 1 1 auto; min-height: 0;
}
.ttc-ad__in img, .ttc-ad__in picture { max-width: 100%; height: auto; display: block; }
.ttc-ad__in ins.adsbygoogle { width: 100%; }

/* ---- ROUND 90: COLLAPSE ON EMPTY ---------------------------------------
   `is-empty` is written by ad-slots.js when AdSense answers "unfilled", or
   when it answers nothing at all and the unit drew nothing -- a blocked
   loader, an ad blocker, or a staging host Google does not serve.

   IT HAS TO WIN OVER EVERY OTHER RULE IN THIS FILE, which is why it is
   `!important` and why it is the only `!important` here. The two sticky units
   are `position: fixed` / `position: sticky` with their own display values set
   at their own breakpoints, and `.ttc-ad--sidebar` turns itself back on inside
   a `@media (min-width: 1201px)` block further down -- so a plain
   `display: none` on the wrapper would be overridden at exactly the widths
   where an empty box is most visible.

   `min-height: 0` as well as `display: none`, and not instead of it: the
   reserved height is a min-height written from the slot's row, and a browser
   that is asked to hide an element still has to be told to stop holding its
   space open when anything re-displays it. The margin goes too -- 24px of gap
   with nothing in it is a smaller version of the same fault.

   THE LABEL GOES WITH IT because the label is inside the wrapper. The rule is
   written out anyway, as a rule rather than a consequence: "no box, no label"
   is the promise, and a promise that depends on where a span happens to sit in
   the markup is one refactor from being broken quietly. */
.ttc-ad.is-empty,
.ttc-ad[data-ad-empty] {
  display: none !important;
  min-height: 0 !important;
  height: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
}
.ttc-ad.is-empty .ttc-ad__label,
.ttc-ad[data-ad-empty] .ttc-ad__label { display: none !important; }

/* ROUND 90: the staging placeholder, which only ever renders on a candidate --
   see the note in app/adboxes.box(). It is drawn as the real unit would be,
   inside the same frame and under the same label, so what Tom is looking at is
   the box and not the placeholder. */
.ttc-ad__stub {
  display: block; max-width: 100%; height: auto; margin: 0 auto;
}

/* ---- ROUND 94: THE TOP-OF-PAGE BAND ------------------------------------
   `.ttc-adtop` is the wrapper app/adboxes.top_band() emits in the position the
   retired 2404 banner held. THE GAP ITSELF IS NOT HERE: it is an inline
   `margin-top` on the element, because this stylesheet is requested only when a
   page actually draws a box and the band's whole job is to hold the space open
   in the states where nothing draws -- a page type with no top slot, a disabled
   slot, or a fill that collapsed. See the note in app/adboxes.py.

   WHAT IS HERE is the one thing that only matters when there IS a box: the box
   gives up its own 24px top margin, so the band owns the gap and the two do not
   add up to 54px. The bottom margin stays -- it is the 23.04px the retired
   banner's wrapper put between itself and the block below it, near enough that
   the page does not move. */
.ttc-adtop { display: block; }
.ttc-adtop > .ttc-ad { margin-top: 0; }

/* ---- THE TWO VARIANTS -------------------------------------------------- */
/* ADSENSE: cream frame, and the label. The label is shown ONLY for adsense
   fills -- app/adboxes decides that, not this file, because "is this paid
   advertising" is a fact about the fill and not a style. */
.ttc-ad--adsense {
  background: #fffeec;
  border: 1px solid #e7dcc6;
  padding: 10px 12px;
}
.ttc-ad__label {
  display: block;
  font: 400 .66rem/1.4 Poppins, system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: .13em;
  color: #9a8f7a;
  margin: 0 0 8px;
  text-align: center;
}
/* HOUSE: green frame, and NO label. A house promotion is ours; calling it
   "Advertisement" would be telling a reader something untrue about it. */
.ttc-ad--house {
  background: #eef4ef;
  border: 1px solid #cfe0d4;
  padding: 10px 12px;
}
.ttc-ad--house .ttc-ad__label { display: none; }

/* ---- THE DESKTOP STICKY SIDEBAR, IN THE RAIL, UNDER THE NEWSLETTER ------
   Hidden everywhere but >=1201, which is where the rail itself appears.
   `position: sticky` inside `#main-right`, which is a floated 303px column,
   so it scrolls with the rail and stops under the header. It is 303px wide
   because the rail is: it holds a 300x600 half page and not one pixel more. */
/* ROUND 94 MOVED THE FLOOR FROM 1400 TO 1201, AND THE REASON IS ABOVE.
   Round 86 chose 1400 because 1201..1399 had the floating Comments/Share bar
   sitting ON the rail; 86b (d) moved that bar to the LEFT from 1201 up -- the
   width at which `#main-right` stops being `display:none` -- and the note at the
   top of this file has said ever since that the unit "could run from 1201" and
   was left at 1400 only because nothing had asked it to move.

   ROUND 94 IS WHAT ASKED. Measured on the candidate, the unit was in the markup
   on all five page types, after the Subscribe box, last child of the rail, and
   `display: none` at 1201, 1280 and 1366 -- so reviewed in any ordinary laptop
   window it was simply not there, which is what "the sidebar sticky is not
   showing" was. The rail is the same 303px at 1201 as it is at 1440 (868, 947,
   1021.3, 1058.3 measured), the Subscribe box does not move, and 1201 is also
   the width below which there is no rail to be in -- so this is the rail's own
   breakpoint rather than a number of ours, and there is no band where the unit
   is shown without a rail to show it in. Below 1201 the rail is hidden and so is
   the unit; on a phone it is `display: none` twice over. */
.ttc-ad--sidebar { display: none; }
@media (min-width: 1201px) {
  .ttc-ad--sidebar {
    display: flex;
    position: sticky;
    /* clear of the site header, which is the only thing above it */
    top: 24px;
    margin: 24px 0 0;
    min-height: var(--adh-d, 600px);
  }

  /* ---- ROUND 86b (c): I TRIED TO DROP THIS RULE AND IT DOES NOT DROP ----
     Tom asked for the sticky ad to sit UNDER the newsletter in the rail and
     stick on scroll -- which is where it already sits, measured at 1440:
     newsletter y216..936, ad y960..1560, inside the rail, at the rail's width
     -- and to drop the out-of-flow rule below IF that placement removes the
     need for it. It does not, and here is the measurement rather than the
     claim. `main` has exactly two children, `#main-left` (float:left) and
     `#main-right` (float:right); four ways to give the rail a runway:

       what                         column x    rail h     sticky travel
       rail left in flow (float)      78.7        1344            0px
       main -> display:flex           38.4       22396      19,000px
       main -> display:grid           38.4       22396      19,000px
       #main-right out of flow        78.7       22413      19,000px   <- kept

     THE NEGATIVE CONTROL IS THE FIRST ROW. With the rail left alone the ad
     renders under the newsletter and `position: sticky` moves it ZERO pixels,
     because a float is only as tall as its contents (1,344px against a
     22,396px article) and the ad is the last thing in it -- there is nothing
     below it to travel into. "Under the newsletter" and "sticks" are two
     requirements and the placement alone only satisfies the first.

     AND MAKING `main` A FLEX OR GRID CONTAINER MOVES THE WHOLE PAGE. 40.36px
     to the left, at 1440, on every page type: `.center` is `width:167rem;
     margin:0 auto` and its auto margins stop resolving evenly the moment
     `main` becomes a flex, grid or flow-root container. Reproduced with
     ad-slots.css disabled entirely, so it is the theme's own behaviour and
     not ours; a fresh 1282.55px `margin:0 auto` div in the same body centres
     correctly under all three, so it is specific to this element. Either
     would shift the reader's column by 40px to move an ad, which is the
     opposite trade of the one Tom is making.

     SO THE OUT-OF-FLOW RULE STAYS, as the least invasive of the four, and it
     is reported as a decision rather than buried. MEASURED AGAIN AT 1440 FOR
     86b, before and after -- nothing but the rail's own height moves:

                       before                  after
       #main-right     x1058 w303 h1344        x1058 w303 h22413
       newsletter      x1058 w303 h720         x1058 w303 h720
       #main-left      x78.7 w979.5 h22395.5   x78.7 w979.5 h22395.5
       main            x78.7 h22414            x78.7 h22414
       document        22897                   22897
       sticky travel   0px                     19,000px

     ONE DECLARATION IS GONE: `main:has(.ttc-ad--sidebar){position:relative}`.
     The theme already sets `position: relative` on BOTH `main` and `.center`,
     so we were restating something true and touching shared furniture to do
     it. The absolute rail's containing block is unchanged.

     SCOPED BY `:has()` TO A PAGE THAT ACTUALLY HAS THE UNIT, and this whole
     stylesheet is only requested when a slot renders -- so with the flag off
     the rail is not described by us at all, which is round 65's rule about
     the shared furniture and the reason this is not in the theme's own file.
     `top` is 1px and not 0 because that is where the float sat: measured, the
     float's top edge is 1px below `main`'s, and reproducing it exactly is how
     the newsletter box does not move by a pixel when a slot turns on. */
  main:has(.ttc-ad--sidebar) #main-right {
    float: none;
    position: absolute;
    right: 0;
    top: 1px;
    bottom: 0;
    width: 303px;
  }
}

/* ---- THE MOBILE STICKY BOTTOM BAR, AND THE BAR IT MUST NOT COVER --------
   PHONE ONLY (<=767px), which is exactly where the floating Comments/Share
   bar is on the RIGHT at 49.4px wide and vertically centred.

   THE COLLISION, AND WHY A MEDIA QUERY IS NOT ENOUGH. The floating bar is
   `top:50%; transform:translateY(-50%)` -- it is centred, so on a tall phone
   it is nowhere near the bottom and on a SHORT one (a landscape phone, a
   browser with every toolbar open) its lower edge comes down to meet a bar
   sitting on the bottom edge. Measured: a 104px-tall floating bar centred in
   a 300px-tall viewport occupies 98..202, and a 58px bottom bar occupies
   242..300 -- 40px apart, and closing.

   So the bottom bar does not merely sit below: it PUSHES THE FLOATING BAR UP
   by half its own height, through `--ttc-fbar-lift`, which recipe-v3-floating
   -bar.css reads. Neither can cover the other's controls at any viewport
   height, because the geometry is arithmetic and not a guess.

   z-index 55 is deliberately BELOW the floating bar (60) and its share popup
   (61): if the two ever did meet, the reader's own controls are the ones that
   stay on top and stay tappable. */
.ttc-ad--mobile-sticky { display: none; }
@media (max-width: 767px) {
  .ttc-ad--mobile-sticky {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 55;
    margin: 0;
    border-radius: 0;
    border-left: 0; border-right: 0; border-bottom: 0;
    min-height: var(--adh-m, 50px);
    /* the bar's own height, published so the floating bar can move off it */
    --bar-h: calc(var(--adh-m, 50px) + 20px);
    padding: 6px 10px;
  }
  /* the dismiss control. A sticky ad a reader cannot get rid of is the one
     ad format every guideline names, so this is not optional furniture. */
  .ttc-ad--mobile-sticky .ttc-ad__x {
    position: absolute; top: 2px; right: 4px;
    width: 30px; height: 30px; line-height: 28px; text-align: center;
    border: 0; background: transparent; cursor: pointer;
    font: 400 18px/28px system-ui, sans-serif; color: #9a8f7a;
  }
  .ttc-ad--mobile-sticky .ttc-ad__x:focus-visible { outline: 2px solid #51000d; }
  /* dismissed for the session -- ad-slots.js sets this and sessionStorage
     remembers it, so it stays gone until the tab is closed. */
  .ttc-ad--mobile-sticky.is-dismissed { display: none; }

  /* AND THE FLOATING BAR MOVES. `--ttc-fbar-lift` is 0 unless a mobile sticky
     ad bar is actually on the page and not dismissed. */
  body:has(.ttc-ad--mobile-sticky:not(.is-dismissed)) {
    --ttc-fbar-lift: 39px;   /* half of 50px reserved + 6+6 padding + 1 border */
  }
}

/* The label sits above a 50px bar awkwardly; on the sticky bar it goes beside
   the creative instead, vertically, so the reserved 50px stays 50px. */
@media (max-width: 767px) {
  .ttc-ad--mobile-sticky .ttc-ad__label {
    position: absolute; left: 8px; top: 50%; transform: translateY(-50%)
              rotate(180deg); writing-mode: vertical-rl;
    margin: 0; font-size: .5rem; letter-spacing: .1em;
  }
  .ttc-ad--mobile-sticky .ttc-ad__in { padding-left: 16px; padding-right: 26px; }
}

/* ---- PRINT. An advertisement is not part of a printed recipe. ---------- */
@media print { .ttc-ad { display: none !important; } }

/* ---- THE LIFT ITSELF, AND WHY IT IS A MARGIN AND NOT A TRANSFORM -------
   This rule lives HERE and not in recipe-v3-floating-bar.css on purpose:
   that stylesheet is live on every recipe and article today, and this round
   deploys nothing. ad-slots.css is loaded only on a page that has a slot, so
   with the flag off this declaration is not on the site at all.

   A MARGIN, because the floating bar's position is a transform -- `top:50%`
   plus `translateY(-50%)` -- and `.ttc-fbar.is-hidden` REPLACES that transform
   with its own `translateY(-50%) translateX(18.2px)`. Folding the lift into
   the transform would mean editing four rules and would silently drop the lift
   the moment the bar hid itself. `margin-top` is not part of the transform, so
   it survives every one of those states, and with `--ttc-fbar-lift` unset it
   computes to 0px and moves nothing. */
.ttc-fbar { margin-top: calc(-1 * var(--ttc-fbar-lift, 0px)); }


/* ---- THE THIRD COLLISION, WHICH WAS NOT ON THE LIST ---------------------
   FOUND BY OPENING THE PHONE FRAME. The job named two pairs to keep apart --
   the sticky bar against the floating Comments/Share bar, and the sidebar
   against the newsletter rail. There is a third thing fixed to the bottom of
   a phone screen on this site and it is the cookie bar: `#ttc-consent`, fixed,
   130px tall, z-index 9999. Measured at 390x844 with the slots on: the consent
   bar occupies y714..844 and the sticky ad bar y794..844 -- the ad is entirely
   inside it, and covered by it.

   WHICH WAY IT WAS ALREADY WRONG MATTERS. The consent bar is on top, so the
   Accept and Decline controls stayed tappable -- an ad covering a consent
   control would have been the serious version of this. What actually happened
   is the other one: a paid unit rendered where nobody could see it, which is
   an impression AdSense should never be asked to count.

   So the ad bar does not appear while there is a cookie question on screen.
   `[hidden]` is the site's OWN dismissal -- app/consent.py ships the bar
   hidden for a reader who has already answered and static/consent/consent.js
   sets `bar.hidden = true` when they answer -- so this needs no script of its
   own and cannot get out of step with the consent bar's real state. */
@media (max-width: 767px) {
  body:has(#ttc-consent:not([hidden])) .ttc-ad--mobile-sticky { display: none; }
  /* and the floating bar drops back to its centre while the ad bar is gone */
  body:has(#ttc-consent:not([hidden])) { --ttc-fbar-lift: 0px; }
}

/* ---- THE IN-FEED BOX IS A GRID ITEM, NOT A BLOCK -----------------------
   `div.list` is a three-column CSS grid whose children are the cards. A box
   dropped into it without this rule is placed as a FOURTH card in a
   three-card row: 303px wide, in the grid's flow, sitting where a recipe
   should be. Spanning every column is what makes it a band between two rows,
   which is what "in-feed, between rows of cards" means. */
.ttc-ad--infeed { grid-column: 1 / -1; }
